text:
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <set>
#include "rpcclient.h"

#include "rpcprotocol.h"
#include "util.h"
#include "ui_interface.h"
#include "chainparams.h" // for Params().RPCPort()

#include <stdint.h>

#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/shared_ptr.hpp>
#include "json/json_spirit_writer_template.h"

using namespace std;
using namespace boost;
using namespace boost::asio;
using namespace json_spirit;

Object CallRPC(const string& strMethod, const Array& params)
{
    if (mapArgs["-rpcuser"] == "" && mapArgs["-rpcpassword"] == "")
        throw runtime_error(strprintf(
            _("You must set rpcpassword=<password> in the configuration file:\n%s\n"
              "If the file does not exist, create it with owner-readable-only file permissions."),
                GetConfigFile().string()));

    // Connect to localhost
    bool fUseSSL = GetBoolArg("-rpcssl", false);
    asio::io_service io_service;
    ssl::context context(io_service, ssl::context::sslv23);
    context.set_options(ssl::context::no_sslv2);
    asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
    SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
    iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);

    bool fWait = GetBoolArg("-rpcwait", false); // -rpcwait means try until server has started
    do {
        bool fConnected = d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort())));
        if (fConnected) break;
        if (fWait)
            MilliSleep(1000);
        else
            throw runtime_error("couldn't connect to server");
    } while (fWait);

    // HTTP basic authentication
    string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
    map<string, string> mapRequestHeaders;
    mapRequestHeaders["Authorization"] = string("Basic ") + strUserPass64;

    // Send request
    string strRequest = JSONRPCRequest(strMethod, params, 1);
    string strPost = HTTPPost(strRequest, mapRequestHeaders);
    stream << strPost << std::flush;

    // Receive HTTP reply status
    int nProto = 0;
    int nStatus = ReadHTTPStatus(stream, nProto);

    // Receive HTTP reply message headers and body
    map<string, string> mapHeaders;
    string strReply;
    ReadHTTPMessage(stream, mapHeaders, strReply, nProto);

    if (nStatus == HTTP_UNAUTHORIZED)
        throw runtime_error("incorrect rpcuser or rpcpassword (authorization failed)");
    else if (nStatus >= 400 && nStatus != HTTP_BAD_REQUEST && nStatus != HTTP_NOT_FOUND && nStatus != HTTP_INTERNAL_SERVER_ERROR)
        throw runtime_error(strprintf("server returned HTTP error %d", nStatus));
    else if (strReply.empty())
        throw runtime_error("no response from server");

    // Parse reply
    Value valReply;
    if (!read_string(strReply, valReply))
        throw runtime_error("couldn't parse reply from server");
    const Object& reply = valReply.get_obj();
    if (reply.empty())
        throw runtime_error("expected reply to have result, error and id properties");

    return reply;
}

class CRPCConvertParam
{
public:
    std::string methodName;            // method whose params want conversion
    int paramIdx;                      // 0-based idx of param to convert
};

static const CRPCConvertParam vRPCConvertParams[] =
{
    { "stop", 0 },
    { "getaddednodeinfo", 0 },
    { "sendtoaddress", 1 },
    { "settxfee", 0 },
    { "getstakedbyaddress", 1 },
    { "getreceivedbyaddress", 1 },
    { "getreceivedbyaccount", 1 },
    { "listreceivedbyaddress", 0 },
    { "listreceivedbyaddress", 1 },
    { "listreceivedbyaccount", 0 },
    { "listreceivedbyaccount", 1 },
    { "getbalance", 1 },
    { "getblock", 1 },
    { "getblockbynumber", 0 },
    { "getblockbynumber", 1 },
    { "getblockhash", 0 },
    { "move", 2 },
    { "move", 3 },
    { "sendfrom", 2 },
    { "sendfrom", 3 },
    { "listtransactions", 1 },
    { "listtransactions", 2 },
    { "listbalances", 0 },
    { "listbalances", 1 },
    { "listbalances", 2 },
    { "listaccounts", 0 },
    { "walletpassphrase", 1 },
    { "walletpassphrase", 2 },
    { "getblocktemplate", 0 },
    { "listsinceblock", 1 },
    { "sendalert", 2 },
    { "sendalert", 3 },
    { "sendalert", 4 },
    { "sendalert", 5 },
    { "sendalert", 6 },
    { "sendmany", 1 },
    { "sendmany", 2 },
    { "reservebalance", 0 },
    { "reservebalance", 1 },
    { "addmultisigaddress", 0 },
    { "addmultisigaddress", 1 },
    { "listunspent", 0 },
    { "listunspent", 1 },
    { "listunspent", 2 },
    { "listunspent", 3 },
    { "getrawtransaction", 1 },
    { "createrawtransaction", 0 },
    { "createrawtransaction", 1 },
    { "signrawtransaction", 1 },
    { "signrawtransaction", 2 },
    { "keypoolrefill", 0 },
    { "importprivkey", 2 },
    { "importwallet", 2 },
    { "dumpbootstrap", 1 },
    { "validateoutputs", 0 },
};

class CRPCConvertTable
{
private:
    std::set<std::pair<std::string, int> > members;

public:
    CRPCConvertTable();

    bool convert(const std::string& method, int idx) {
        return (members.count(std::make_pair(method, idx)) > 0);
    }
};

CRPCConvertTable::CRPCConvertTable()
{
    const unsigned int n_elem =
        (sizeof(vRPCConvertParams) / sizeof(vRPCConvertParams[0]));

    for (unsigned int i = 0; i < n_elem; i++) {
        members.insert(std::make_pair(vRPCConvertParams[i].methodName,
                                      vRPCConvertParams[i].paramIdx));
    }
}

static CRPCConvertTable rpcCvtTable;

// Convert strings to command-specific RPC representation
Array RPCConvertValues(const std::string &strMethod, const std::vector<std::string> &strParams)
{
    Array params;

    for (unsigned int idx = 0; idx < strParams.size(); idx++) {
        const std::string& strVal = strParams[idx];

        // insert string value directly
        if (!rpcCvtTable.convert(strMethod, idx)) {
            params.push_back(strVal);
        }

        // parse string as JSON, insert bool/number/object/etc. value
        else {
            Value jVal;
            if (!read_string(strVal, jVal))
                throw runtime_error(string("Error parsing JSON:")+strVal);
            params.push_back(jVal);
        }

    }

    return params;
}

int CommandLineRPC(int argc, char *argv[])
{
    string strPrint;
    int nRet = 0;
    try
    {
        // Skip switches
        while (argc > 1 && IsSwitchChar(argv[1][0]))
        {
            argc--;
            argv++;
        }

        // Method
        if (argc < 2)
            throw runtime_error("too few parameters");
        string strMethod = argv[1];

        // Parameters default to strings
        std::vector<std::string> strParams(&argv[2], &argv[argc]);
        Array params = RPCConvertValues(strMethod, strParams);

        // Execute
        Object reply = CallRPC(strMethod, params);

        // Parse reply
        const Value& result = find_value(reply, "result");
        const Value& error  = find_value(reply, "error");

        if (error.type() != null_type)
        {
            // Error
            strPrint = "error: " + write_string(error, false);
            int code = find_value(error.get_obj(), "code").get_int();
            nRet = abs(code);
        }
        else
        {
            // Result
            if (result.type() == null_type)
                strPrint = "";
            else if (result.type() == str_type)
                strPrint = result.get_str();
            else
                strPrint = write_string(result, true);
        }
    }
    catch (boost::thread_interrupted) {
        throw;
    }
    catch (std::exception& e) {
        strPrint = string("error: ") + e.what();
        nRet = 87;
    }
    catch (...) {
        PrintException(NULL, "CommandLineRPC()");
    }

    if (strPrint != "")
    {
        fprintf((nRet == 0 ? stdout : stderr), "%s\n", strPrint.c_str());
    }
    return nRet;
}


text:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>

#include "safe_ptr.hpp"

#include <functional>

using namespace spl;

struct number
{
  int i;

  number() : i(1) {}
  number(int j) : i(j) {}
  number(int j, int k) : i(j+k) {}
  number(int j, int k, int l, int m, int n) : i(j+k+l+m+n) {}
  number(int j, int k, int l, int m, int n, int o) : i(j+k+l+m+n+o) {}
};

BOOST_AUTO_TEST_CASE( test_shared_ptr_to_safe_ptr )
{
  std::shared_ptr<number> p(new number());
  safe_ptr<number> q(p);
  BOOST_CHECK_EQUAL(q->i, 1);
}

BOOST_AUTO_TEST_CASE( test_make_shared_to_safe_ptr )
{
  safe_ptr<number> p(std::make_shared<number>());
  BOOST_CHECK_EQUAL(p->i, 1);
}

BOOST_AUTO_TEST_CASE( test_safe_ptr_default )
{
  safe_ptr<number> p;
  BOOST_CHECK_EQUAL(p->i, 1);
}

BOOST_AUTO_TEST_CASE( test_make_safe )
{
  safe_ptr<number> p(make_safe<number>(2));
  BOOST_CHECK_EQUAL(p->i, 2);

  p = make_safe<number>(1,2);
  BOOST_CHECK_EQUAL(p->i, 3);

  p = make_safe<number>(1,2,3,4,5);
  BOOST_CHECK_EQUAL(p->i, 15);

#ifdef SPL_HAS_VARIADIC_TEMPLATES
  p = make_safe<number>(1,2,3,4,5,6);
  BOOST_CHECK_EQUAL(p->i, 21);
#endif
}

class event_notifier
{
    std::function<void (int)> event_handler_;
  public:
    void notify_me(std::function<void (int)> handler)
    {
      event_handler_ = handler;
    }
    void fire_event(int i)
    {
      if (event_handler_) { event_handler_(i); }
    }
};

class event_handler : public enable_safe_from_this<event_handler>
{
    int i_;

    void handle_event(int i)
    {
      i_ = i;
    }

  public:
    event_handler() {}
    event_handler(int i) : i_(i) {}

    int i() { return i_; }

    void do_something(event_notifier & notifier)
    {
      using namespace std::placeholders;
      auto fun = std::bind(&event_handler::handle_event, safe_from_this(), _1);
      notifier.notify_me(fun);
    }
};

BOOST_AUTO_TEST_CASE( test_safe_this )
{
  std::weak_ptr<event_handler> weakie;
  {
    event_notifier notifie;
    {
      safe_ptr<event_handler> handie;
      handie = make_safe<event_handler>(101);
      BOOST_CHECK_EQUAL( handie->i(), 101 );
      handie->do_something(notifie);
      notifie.fire_event(42);
      BOOST_CHECK_EQUAL( handie->i(), 42 );
      weakie = handie;
    }
    BOOST_CHECK(!weakie.expired()); // weakie still finds handie is alive
    notifie.fire_event(13);  // will not crash
  }
  // but now handie has been cleaned up and not leaked
  BOOST_CHECK(weakie.expired());
}

ext: cpp

max_stars_repo_name: castedo/safe-ptr

max_issues_repo_name: castedo/safe-ptr

max_forks_repo_name: castedo/safe-ptr


text:
/////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Olaf Krzikalla 2004-2006.
// (C) Copyright Ion Gaztanaga  2006-2013.
//
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
/////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP
#define BOOST_INTRUSIVE_DETAIL_ITESTVALUE_HPP

#include <iostream>
#include <boost/intrusive/options.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include "nonhook_node.hpp"
#include "int_holder.hpp"
#include <boost/intrusive/detail/get_value_traits.hpp>
#include <boost/container/vector.hpp>

namespace boost{
namespace intrusive{

struct testvalue_filler
{
   void *dummy_[3];
};

template<class Hooks>
struct testvalue
   :  testvalue_filler
   ,  Hooks::base_hook_type
   ,  Hooks::auto_base_hook_type
{
   typename Hooks::member_hook_type        node_;
   typename Hooks::auto_member_hook_type   auto_node_;
   typename Hooks::nonhook_node_member_type nhn_member_;

   int_holder value_;

   testvalue()
   {}

   explicit testvalue(int i)
      :  value_(i)
   {}

   testvalue (const testvalue& src)
      :  value_(src.value_)
   {}

   // testvalue is used in boost::container::vector and thus prev and next
   // have to be handled appropriately when copied:
   testvalue & operator= (const testvalue& src)
   {
      Hooks::base_hook_type::operator=(static_cast<const typename Hooks::base_hook_type&>(src));
      Hooks::auto_base_hook_type::operator=(static_cast<const typename Hooks::auto_base_hook_type&>(src));
      this->node_       = src.node_;
      this->auto_node_  = src.auto_node_;
      this->nhn_member_ = src.nhn_member_;
      value_ = src.value_;
      return *this;
   }

   void swap_nodes(testvalue &other)
   {
      Hooks::base_hook_type::swap_nodes(static_cast<typename Hooks::base_hook_type&>(other));
      Hooks::auto_base_hook_type::swap_nodes(static_cast<typename Hooks::auto_base_hook_type&>(other));
      node_.swap_nodes(other.node_);
      auto_node_.swap_nodes(other.auto_node_);
      nhn_member_.swap_nodes(other.nhn_member_);
   }

   bool is_linked() const
   {
      return Hooks::base_hook_type::is_linked() ||
      Hooks::auto_base_hook_type::is_linked() ||
      node_.is_linked() ||
      auto_node_.is_linked() ||
      nhn_member_.is_linked();
   }

   const int_holder &get_int_holder() const
   {  return value_; }

   int int_value() const
   {  return value_.int_value();  }

   ~testvalue()
   {}

   bool operator< (const testvalue &other) const
   {  return value_ < other.value_;  }

   bool operator> (const testvalue &other) const
   {  return value_ > other.value_;  }

   bool operator==(const testvalue &other) const
   {  return value_ == other.value_;  }

   bool operator!=(const testvalue &other) const
   {  return value_ != other.value_;  }

   friend bool operator< (int other1, const testvalue &other2)
   {  return other1 < other2.value_.int_;  }

   friend bool operator> (int other1, const testvalue &other2)
   {  return other1 > other2.value_.int_;  }

   friend bool operator< (const testvalue &other1, int other2)
   {  return other1.value_.int_ < other2;  }

   friend bool operator> (const testvalue &other1, int other2)
   {  return other1.value_.int_ > other2;  }

   friend bool operator== (int other1, const testvalue &other2)
   {  return other1 == other2.value_.int_;  }

   friend bool operator== (const testvalue &other1, int other2)
   {  return other1.value_.int_ == other2;  }

   friend bool operator!= (int other1, const testvalue &other2)
   {  return other1 != other2.value_.int_;  }

   friend bool operator!= (const testvalue &other1, int other2)
   {  return other1.value_.int_ != other2;  }

   friend std::size_t hash_value(const testvalue&t)
   {
      boost::hash<int> hasher;
      return hasher((&t)->int_value());
   }
};

template<class T>
std::size_t priority_hash(const T &t)
{  return boost::hash<int>()((&t)->int_value()); }

std::size_t priority_hash(int i)
{  return boost::hash<int>()(i); }

template <class T, class U>
bool priority_order(const T& t1, const U& t2)
{
   std::size_t hash1 = (priority_hash)(t1);
   boost::hash_combine(hash1, -hash1);
   std::size_t hash2 = (priority_hash)(t2);
   boost::hash_combine(hash2, -hash2);
   return hash1 < hash2;
}

template < typename Node_Algorithms, class Hooks>
void swap_nodes(testvalue<Hooks>& lhs, testvalue<Hooks>& rhs)
{
    lhs.swap_nodes(rhs);
}

template<class Hooks>
std::ostream& operator<<
   (std::ostream& s, const testvalue<Hooks>& t)
{  return s << t.value_.int_value();   }

struct even_odd
{
   template < typename key_type_1, typename key_type_2 >
   bool operator()
      (const key_type_1& v1
      ,const key_type_2& v2) const
   {
      if (((&v1)->int_value() & 1) == ((&v2)->int_value() & 1))
         return (&v1)->int_value() < (&v2)->int_value();
      else
         return (&v2)->int_value() & 1;
   }
};

struct is_even
{
   template <typename key_type>
   bool operator()
      (const key_type& v1) const
   {  return ((&v1)->int_value() & 1) == 0;  }
};

struct is_odd
{
   template <typename key_type>
   bool operator()
      (const key_type& v1) const
   {  return ((&v1)->int_value() & 1) != 0;  }
};

template <typename>
struct ValueContainer;

template < class Hooks>
struct ValueContainer< testvalue<Hooks> >
{
    typedef boost::container::vector< testvalue<Hooks> > type;
};

template < typename Pointer >
class heap_node_holder
{
   typedef typename pointer_traits<Pointer>::element_type element_type;
   typedef Pointer pointer;
   typedef typename pointer_rebind<pointer, const element_type>::type const_pointer;

   public:
   heap_node_holder()
      : m_ptr(pointer_traits<Pointer>::pointer_to(*new element_type))
   {}

   ~heap_node_holder()
   { delete &*m_ptr;   }

   const_pointer get_node() const
   { return m_ptr; }

   pointer get_node()
   { return m_ptr; }

   private:
   pointer m_ptr;
};

template<class Hooks>
struct testvalue_traits
   : public Hooks
{
   typedef testvalue< Hooks > value_type;

   //base
   typedef typename detail::get_base_value_traits
         < value_type
         , typename Hooks::base_hook_type
         >::type base_value_traits;
   //auto-base
   typedef typename detail::get_base_value_traits
         < value_type
         , typename Hooks::auto_base_hook_type
         >::type auto_base_value_traits;
   //member
   typedef typename detail::get_member_value_traits
         < member_hook
            < value_type
            , typename Hooks::member_hook_type
            , &value_type::node_
            >
         >::type member_value_traits;
   //auto-member
   typedef typename detail::get_member_value_traits
         < member_hook
            < value_type
            , typename Hooks::auto_member_hook_type
            , &value_type::auto_node_
            >
         >::type auto_member_value_traits;
   //nonmember
   typedef nonhook_node_member_value_traits
         < value_type
         , typename Hooks::nonhook_node_member_type
         , &value_type::nhn_member_
         , safe_link
         > nonhook_value_traits;
};

}  //namespace intrusive{
}  //namespace boost{

bool priority_order(int t1, int t2)
{
   std::size_t hash1 = boost::hash<int>()(t1);
   boost::hash_combine(hash1, &t1);
   std::size_t hash2 = boost::hash<int>()(t2);
   boost::hash_combine(hash2, &t2);
   return hash1 < hash2;
}

#endif

ext: hpp


text:
//          Copyright Victor Smirnov 2017.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#pragma once

#include <boost/config.hpp>

#include <boost/assert.hpp>

#include <memoria/fiber/context.hpp>
#include <memoria/fiber/detail/config.hpp>
#include <memoria/fiber/detail/spinlock.hpp>

#include <memoria/fiber/mutex.hpp>
#include <memoria/fiber/recursive_mutex.hpp>
#include <memoria/fiber/condition_variable.hpp>
#include <memoria/fiber/operations.hpp>

#include <cstdint>
#include <mutex>

#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable:4251)
#endif

namespace memoria {
namespace fibers {

// Note that this shared mutex is not up/down-gradable. That means an owner holding
// exclusive lock must not obtain shared lock and vise versa.

class recursive_shared_mutex {
    using Mutex     = mutex;
    using FiberId   = typename fiber::id;

    Mutex lock_;
    condition_variable shared_cv_;
    condition_variable exclusive_cv_;

    uint64_t shared_locks_, exclusive_locks_;
    uint64_t shared_waiters_, exclusive_waiters_;

    FiberId exclusive_owner_id_;
public:
    void lock_shared()
    {
        std::unique_lock<Mutex> guard(lock_);

        if (exclusive_locks_ || exclusive_waiters_)
        {
            shared_waiters_++;

            shared_cv_.wait(guard, [this]{
                return !(exclusive_locks_ || exclusive_waiters_);
            });

            shared_waiters_--;
        }

        shared_locks_++;
    }

    void unlock_shared()
    {
        std::unique_lock<Mutex> guard(lock_);

        shared_locks_--;

        if (exclusive_waiters_)
        {
            exclusive_cv_.notify_one();
        }
    }

    bool try_lock_shared()
    {
        std::unique_lock<Mutex> guard(lock_);

        if (exclusive_locks_ || exclusive_waiters_)
        {
            return false;
        }

        shared_locks_++;

        return true;
    }

    void lock()
    {
        std::unique_lock<Mutex> guard(lock_);

        if (shared_locks_ || is_locked_exclusively_not_by_me())
        {
            exclusive_waiters_++;

            exclusive_cv_.wait(guard, [this]{
                return !(shared_locks_ || is_locked_exclusively_not_by_me());
            });

            exclusive_waiters_--;
        }

        exclusive_locks_++;
        exclusive_owner_id_ = this_fiber::get_id();
    }

    void unlock()
    {
        std::unique_lock<Mutex> guard(lock_);

        if (--exclusive_locks_ == 0)
        {
            exclusive_owner_id_ = FiberId();

            if (exclusive_waiters_)
            {
                exclusive_cv_.notify_one();
            }
            else if (shared_waiters_)
            {
                shared_cv_.notify_all();
            }
        }
    }

    bool try_lock()
    {
        std::unique_lock<Mutex> guard(lock_);

        if (shared_locks_ || is_locked_exclusively_not_by_me())
        {
            return false;
        }

        exclusive_locks_++;

        return true;
    }

private:
    bool is_locked_exclusively_not_by_me() const {
        return exclusive_locks_ && exclusive_owner_id_ != this_fiber::get_id();
    }
};

}}

max_stars_repo_name: victor-smirnov/memoria

max_issues_repo_name: victor-smirnov/memoria

max_forks_repo_name: victor-smirnov/memoria


text:
#pragma once
#include "types.hpp"
#include "lubee/src/size.hpp"
#include "../sdl/tls.hpp"
#include "../handle/opengl.hpp"
#include "lubee/src/rect.hpp"
#include <boost/variant.hpp>

namespace rev {
	class GLFBufferCore {
		public:
			void use_begin() const;
			static TLS<lubee::SizeI> s_fbSize;

			DefineEnumPair(Att,
				((Color0)(0x00))
				#ifndef USE_OPENGLES2
					((Color1)(0x01))
					((Color2)(0x02))
					((Color3)(0x03))
				#endif
				((Depth)(0x04))
				((Stencil)(0x05))
				((NumAttachment)(0x06))
				#ifndef USE_OPENGLES2
					((DepthStencil)(0x07))
				#endif
			);
			static FBInfo GetCurrentInfo(Att::e att);
			static GLenum _AttIdtoGL(Att::e att);
			void _attachRenderbuffer(Att::e aId, GLuint rb);
			void _attachCubeTexture(Att::e aId, GLuint faceFlag, GLuint tb, MipLevel level);
			void _attachTexture(Att::e aId, GLuint tb, MipLevel level);
			struct TexRes {
				HTexSrc			tex;
				CubeFace		face;
				MipLevel		level;
			};

			struct RawTex {
				GLuint			id;
				MipLevel		level;

				void invalidate() noexcept;
				bool operator == (const RawTex& t) const noexcept;
			};
			struct RawRb {
				GLuint	id;

				void invalidate() noexcept;
				bool operator == (const RawRb& r) const noexcept;
			};
			// attachは受け付けるがハンドルを格納するだけであり、実際OpenGLにセットされるのはDrawThread
		protected:
			// 内部がTextureかRenderBufferなので、それらを格納できる型を定義
			using Res = boost::variant<boost::blank, RawTex, RawRb, TexRes, HRb>;
			GLuint	_idFbo;
			static void _SetCurrentFBSize(const lubee::SizeI& s);

		public:
			static const lubee::SizeI& GetCurrentFBSize() noexcept;
			GLFBufferCore() = default;
			GLFBufferCore(GLuint id);
			GLuint getBufferId() const;
	};
	namespace draw {
		class IQueue;
	}
	using Size_OP = spi::Optional<lubee::SizeI>;
	class LuaState;
	//! OpenGL: FrameBufferObjectインタフェース
	class GLFBuffer :
		public GLFBufferCore,
		public IGLResource,
		public std::enable_shared_from_this<GLFBuffer>
	{
		private:
			// GLuintは内部処理用 = RenderbufferのId
			Res	_attachment[Att::NumAttachment];
			template <class T>
			void _attachIt(Att::e att, const T& arg);

		public:
			static Size_OP GetAttachmentSize(const Res (&att)[Att::NumAttachment], Att::e id);
			static void LuaExport(LuaState& lsc);
			GLFBuffer();
			~GLFBuffer();
			void attachRBuffer(Att::e att, const HRb& hRb);
			void attachTexture(Att::e att, const HTexSrc& hTex, MipLevel level);
			void attachTextureFace(Att::e att, const HTexSrc& hTex, CubeFace face, MipLevel level);
			void attachRawRBuffer(Att::e att, GLuint idRb);
			void attachRawTexture(Att::e att, GLuint idTex, MipLevel level);
			void attachOtherAttachment(Att::e attDst, Att::e attSrc, const HFb& hFb);
			void detach(Att::e att);

			void onDeviceReset() override;
			void onDeviceLost() override;
			void dcmd_export(draw::IQueue& q) const;
			const Res& getAttachment(Att::e att) const;
			HTexSrc getAttachmentAsTexture(Att::e id) const;
			HRb getAttachmentAsRBuffer(Att::e id) const;
			Size_OP getAttachmentSize(Att::e att) const;
			const char* getResourceName() const noexcept override;
	};
}
#include "../lua/import.hpp"
DEF_LUAIMPORT(rev::GLFBuffer)

max_stars_repo_name: degarashi/revenant

max_issues_repo_name: degarashi/revenant

max_forks_repo_name: degarashi/revenant


text:
// Copyright (C) 2014-2015 Vicente J. Botet Escriba
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

// <boost/thread/experimental/parallel/v1/exception_list.hpp>

#define BOOST_THREAD_VERSION 4
#define BOOST_THREAD_PROVIDES_EXECUTORS
#include <boost/config.hpp>
#if ! defined  BOOST_NO_CXX11_DECLTYPE
#define BOOST_RESULT_OF_USE_DECLTYPE
#endif

#include <boost/thread/experimental/parallel/v2/task_region.hpp>
#include <string>

#include <boost/detail/lightweight_test.hpp>

#if ! defined BOOST_NO_CXX11_LAMBDAS  && defined(BOOST_THREAD_PROVIDES_INVOKE)
using boost::experimental::parallel::v2::task_region;
using boost::experimental::parallel::v2::task_region_handle;
using boost::experimental::parallel::v1::exception_list;

void run_no_exception()
{
  std::string s("test");
  bool parent_flag = false;
  bool task1_flag = false;
  bool task2_flag = false;
  bool task21_flag = false;
  bool task3_flag = false;
  task_region([&](task_region_handle& trh)
      {
        parent_flag = true;
        trh.run([&]()
            {
              task1_flag = true;
              std::cout << "task1: " << s << std::endl;
            });
        trh.run([&]()
            {
              task2_flag = true;
              std::cout << "task2" << std::endl;
              task_region([&](task_region_handle& trh)
                  {
                    trh.run([&]()
                        {
                          task21_flag = true;
                          std::cout << "task2.1" << std::endl;
                        });
                  });
            });
        int i = 0, j = 10, k = 20;
        trh.run([=, &task3_flag]()
            {
              task3_flag = true;
              std::cout << "task3: " << i << " " << j << " " << k << std::endl;
            });
        std::cout << "parent" << std::endl;
      });
  BOOST_TEST(parent_flag);
  BOOST_TEST(task1_flag);
  BOOST_TEST(task2_flag);
  BOOST_TEST(task21_flag);
  BOOST_TEST(task3_flag);
}

void run_no_exception_wait()
{
  std::string s("test");
  bool parent_flag = false;
  bool wait_flag = false;
  bool task1_flag = false;
  bool task2_flag = false;
  bool task21_flag = false;
  bool task3_flag = false;
  task_region([&](task_region_handle& trh)
      {
        parent_flag = true;
        trh.run([&]()
            {
              task1_flag = true;
              std::cout << "task1: " << s << std::endl;
            });
        trh.run([&]()
            {
              task2_flag = true;
              std::cout << "task2" << std::endl;
              task_region([&](task_region_handle& trh)
                  {
                    trh.run([&]()
                        {
                          task21_flag = true;
                          std::cout << "task2.1" << std::endl;
                        });
                  });
            });
        int i = 0, j = 10, k = 20;
        trh.run([=, &task3_flag]()
            {
              task3_flag = true;
              std::cout << "task3: " << i << " " << j << " " << k << std::endl;
            });
        std::cout << "before" << std::endl;
        trh.wait();
        wait_flag = true;
        std::cout << "parent" << std::endl;
      });
  BOOST_TEST(parent_flag);
  BOOST_TEST(wait_flag);
  BOOST_TEST(task1_flag);
  BOOST_TEST(task2_flag);
  BOOST_TEST(task21_flag);
  BOOST_TEST(task3_flag);
}

void run_exception_1()
{
  try
  {
    task_region([](task_region_handle& trh)
        {
          trh.run([]()
              {
                std::cout << "task1" << std::endl;
                throw 1;
              });
          boost::this_thread::sleep_for(boost::chrono::seconds(1));
          trh.run([]()
              {
                std::cout << "task3" << std::endl;
              });
#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED
          BOOST_TEST(false);
#endif
        });
    BOOST_TEST(false);
  }
  catch (exception_list const& e)
  {
    BOOST_TEST_EQ(e.size(), 1u);
  }
  catch (...)
  {
    BOOST_TEST(false);
  }
}

void run_exception()
{
  try
  {
    task_region([](task_region_handle& trh)
        {
          trh.run([]()
              {
                std::cout << "task1" << std::endl;
                throw 1;
              });
          trh.run([]()
              {
                std::cout << "task2" << std::endl;
                throw 2;
              });
          boost::this_thread::sleep_for(boost::chrono::seconds(1));
          trh.run([]()
              {
                std::cout << "task3" << std::endl;
                throw 3;
              });
          std::cout << "parent" << std::endl;
          throw 100;
        });
    BOOST_TEST(false);
  }
  catch (exception_list const& el)
  {
    BOOST_TEST(el.size() >= 1u);
    for (boost::exception_ptr const& e: el)
    {
      try {
        boost::rethrow_exception(e);
      }
      catch (boost::exception&)
      {
        BOOST_TEST(true);
      }
      catch (int i) // this doesn't works yet
      {
        BOOST_TEST((i == 1) || (i == 2) || (i == 3));
      }
      catch (...)
      {
        BOOST_TEST(false);
      }
    }
  }
  catch (...)
  {
    BOOST_TEST(false);
  }
}

void run_nested_exception()
{
  std::string s("test");
  bool parent_flag = false;
  bool task1_flag = false;
  bool task2_flag = false;
  bool task21_flag = false;
  bool task3_flag = false;
  try
  {
  task_region([&](task_region_handle& trh)
      {
        parent_flag = true;
        trh.run([&]()
            {
              task1_flag = true;
              std::cout << "task1: " << s << std::endl;
            });
        trh.run([&]()
            {
              task2_flag = true;
              std::cout << "task2" << std::endl;
              task_region([&](task_region_handle& trh)
                  {
                    trh.run([&]()
                        {
                          task21_flag = true;
                          std::cout << "task2.1" << std::endl;
                          throw 21;
                        });
                  });
            });
        int i = 0, j = 10, k = 20;
        trh.run([=, &task3_flag]()
            {
              task3_flag = true;
              std::cout << "task3: " << i << " " << j << " " << k << std::endl;
            });
        std::cout << "parent" << std::endl;
      });
  }
  catch (exception_list const& el)
  {
    BOOST_TEST(el.size() == 1u);
    for (boost::exception_ptr const& e: el)
    {
      try {
        boost::rethrow_exception(e);
      }
      catch (int i) // this doesn't works yet
      {
        BOOST_TEST_EQ(i, 21);
      }
      catch (boost::exception&)
      {
        BOOST_TEST(true);
      }
      catch (...)
      {
        BOOST_TEST(false);
      }
    }
  }
  catch (...)
  {
    BOOST_TEST(false);
  }
  BOOST_TEST(parent_flag);
  BOOST_TEST(task1_flag);
  BOOST_TEST(task2_flag);
  BOOST_TEST(task21_flag);
}

int main()
{
  run_no_exception();
  run_no_exception_wait();
  run_exception();
  run_exception_1();
  run_nested_exception();
  return boost::report_errors();
}
#else
int main()
{
  return boost::report_errors();
}
#endif


text:
//  File:        NProjectMPPXMLData.cpp
//  Copyright:   Copyright(C) 2013-2017 Wuhan KOTEI Informatics Co., Ltd. All rights reserved.
//  Website:     http://www.nuiengine.com
//  Description:  This code is part of NPlan Project (Powered by NUI Engine)
//  Comments:
//  Rev:         1
//  Created:     2018/8/27
//  Last edit:   2015/2/27
//  Author:      Chen Zhi and his team
//  E-mail:       cz_666@qq.com
//  License: APACHE V2.0 (see license file)
#include "NProjectMPPXMLData.h"
#include "../manager/KProjectManager.h"
#include <numeric>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost:: posix_time;

CNProjectMPPXMLData::CNProjectMPPXMLData ( CNProjectData* pData ) : CNProjectBaseFile( pData )
{
    m_p_xmldoc = NULL;
    m_p_root   = NULL;
    m_is_nplan_format = false;
}

CNProjectMPPXMLData::~CNProjectMPPXMLData( void )
{
    if ( m_p_xmldoc )
    {
        delete m_p_xmldoc;
    }
}

//加载xml文件
int CNProjectMPPXMLData::load( kn_string &filename )
{
    int _result = ERROR_FUNCTION_FAILED;

    string file = ns2s( filename );
    m_p_xmldoc = new TiXmlDocument( file.c_str());
    if( NULL == m_p_xmldoc )
    {
        return ERROR_FILE_NOT_FOUND;
    }

    if ( !m_p_xmldoc->LoadFile())
    {
        return ERROR_FILE_INVALID;
    }

    m_p_root = m_p_xmldoc->RootElement();

    if( m_pPrjData != NULL)
    {
		//先解析资源，再解析基本信息。以便将基本信息中的PM名称转化为ID
		parseResources();

		parseBaseInfo();

		_result = parseTasks();

        if ( _result != NO_ERROR )
        {
            return _result;
        }

        parseAssignment();
    }

    return NO_ERROR;
}

//解析项目基本信息
bool CNProjectMPPXMLData:: parseBaseInfo()
{
    if( m_p_root == NULL )
    {
        return false;
    }

   /* kn_string str_name = getChildNodeText( m_p_root, "Title" );
    if( !str_name.empty() && (kn_string::npos == str_name.find( _T( "MSProj" )) ))
    {
        m_pPrjData->setName( str_name.c_str());
    }*/

    //标识此文件格式为NPlan导出的扩展格式
    kn_string str_name = getChildNodeText( m_p_root, "NPlan" );
    m_is_nplan_format = ( str_name == _T("1") );

    //m_pPrjData->m_baseinfo.setLeader( getChildNodeText( m_p_root, "Manager" ).c_str());
	//PM也是资源，应保存资源ID，而不是名称
	int pm_id = m_pPrjData->m_respool.findResourceID( getChildNodeText( m_p_root, "Manager" ).c_str() );
	m_pPrjData->m_baseinfo.setId(pm_id);

    return true;
}

//解析资源
bool CNProjectMPPXMLData:: parseResources()
{
    bool _result = false;

    if( NULL == m_p_root )
    {
        return _result;
    }

    TiXmlElement* p_resources = m_p_root->FirstChildElement( "Resources" );
    if( NULL == p_resources )
    {
        return _result;
    }

    TiXmlElement* p_res = p_resources->FirstChildElement( "Resource" );
    if( NULL == p_res )
    {
        return _result;
    }

    _result = true;

	CNProjectResourcePool* p_res_pool = getProjectManager()->getGlobalResource();

    for (; p_res != NULL; p_res = p_res->NextSiblingElement())
    {
        kn_string str_text = getChildNodeText( p_res, "Name" );
        if( str_text.empty())
        {
            continue;
        }

		CNProjectResource res( str_text.c_str(), getChildNodeValue( p_res, "UID" ), -1 );

		//全局资源池中去查找匹配的资源，以便获取资源类型
		if(p_res_pool)
		{
			if( res.getId() == p_res_pool->findResourceGroupID( res.getName().c_str() ) )
			{
				res.setType( p_res_pool->getResourceType( res.getId() ) );
			}
		}

        m_pPrjData->m_respool.addResource( res );
    }

    return _result;
}

//查找第一个有效的任务节点
TiXmlElement* CNProjectMPPXMLData::findFirstValidTaskElem()
{
    TiXmlElement* first_task_element = NULL;

    TiXmlElement* p_tasks = m_p_root->FirstChildElement( "Tasks" );

    if( NULL == p_tasks )
    {
        return first_task_element;
    }

    TiXmlElement* p_task = p_tasks->FirstChildElement();

    if ( p_task && (0 == getChildNodeValue( p_task, "OutlineLevel" ))) //MS Project中的非显示用对象
    {
        m_pPrjData->setName( getChildNodeText( p_task, "Name" ).c_str() );
        m_pPrjData->m_baseinfo.setProDescribe( getChildNodeText( p_task, "Notes" ).c_str() );
        p_task = p_task->NextSiblingElement();
    }

    if( NULL == p_task )
    {
        return first_task_element;
    }

    first_task_element = p_task;

    vector <int> vect_level;

    for (; p_task != NULL; p_task = p_task->NextSiblingElement())
    {
        int level = getChildNodeValue( p_task, "OutlineLevel" ); //任务层数
        if( level > 3 )
        {
            //因为NPlan中只支持任务及子任务两层结构，任务层数>3的格式不支持
            first_task_element = NULL;
            return first_task_element;
        }

        vect_level.push_back( level );
    }

    vector <int>::iterator f = std::max_element( vect_level.begin(), vect_level.end());
    if( f != vect_level.end())
    {
        if((*f) == 3 )
        {
            //任务层数=3，但是在在多个1级任务的，也不支持(1级任务只能当作项目名称，且仅有一个)
            if ( std::count( vect_level.begin(), vect_level.end(), 1 ) > 1 )
            {
                first_task_element = NULL;
                return first_task_element;
            }
            else
            {
                //自动过滤1级节点（项目名称）
                first_task_element = first_task_element->NextSiblingElement();
            }
        }
    }

    return first_task_element;
}

//计算两个时间之间的间隔，返回间隔天数和小时数
void CNProjectMPPXMLData::calcTimeInterval( kn_string &start_time, kn_string &end_time, OUT int& days, OUT int& hours )
{
    days = hours = 0; //clear first

    if( start_time.empty() || end_time.empty())
    {
        return;
    }

    ptime begin_time = timestr2ptime( start_time );
    if( begin_time.is_not_a_date_time())
    {
        return;
    }

    ptime finish_time = timestr2ptime( end_time );
    if( finish_time.is_not_a_date_time())
    {
        return;
    }

    boost::posix_time::time_duration apart_time = finish_time -begin_time;

    days  = apart_time.hours() / 24;
    hours = apart_time.hours() % 24;
}

int CNProjectMPPXMLData::calcActionStateByPercent(int precent)
{
    int action_state = 0;

    if( precent <= 0 )
    {
        action_state = 0; //TODO
    }
    else if( precent == 100 )
    {
        action_state = 3; //DONE
    }
    else
    {
        if(m_is_nplan_format)
        {
            if ( precent <= 40 )
            {
                action_state = 1; //IN PROGRESS
            }
            else if( precent >= 80)
            {
                action_state = 2; //VERIFY
            }
        }
        else
        {
            if( precent >= 50 )
            {
                action_state = 2; //VERIFY
            }
            else
            {
                precent = 1; //IN PROGRESS
            }
        }
    }

    return action_state;
}

//解析任务列表
int CNProjectMPPXMLData::parseTasks()
{
    int _result = NO_ERROR;

    if( NULL == m_p_root )
    {
        return _result;
    }

    TiXmlElement* p_task = findFirstValidTaskElem();
    if( NULL == p_task )
    {
        return ERROR_FILE_INVALID;
    }

    CNProjectMileStone milestone;
    CNProjectTask task;
    CNProjectTaskCard action;

    bool first_time = true;

    int days( 0 ), hours( 0 );

    int outline_level = getChildNodeValue( p_task, "OutlineLevel" ); //TASK的级别

    for (; p_task != NULL; p_task = p_task->NextSiblingElement())
    {
        kn_string str_text = getChildNodeText( p_task, "Name" );
        if( str_text.empty())
        {
            continue;
        }

        int level = getChildNodeValue( p_task, "OutlineLevel" ); //任务层数
        if( outline_level == level )
        {
            if( !first_time ) //插入完task card后，再添加进数组
            {
                m_pPrjData->addTask( task );
                task.clearTaskCards();
                task.setName( _T( "" )); //清空名称，用来判断是否已经保存
            }

            //TODO:MS PROJECT 一级任务没有责任人
            task.setName( str_text.c_str());
            task.setId( getChildNodeValue( p_task, "UID" ));
            task.setStartTime( getChildNodeText( p_task, "Start" ).c_str());
            task.setEndTime( getChildNodeText( p_task, "Finish" ).c_str());
            task.setTaskDescribe( getChildNodeText( p_task, "Notes" ).c_str());

            first_time = false;
        }
        else
        {
            action.setName( str_text.c_str());
            action.setId( getChildNodeValue( p_task, "UID" ));

            kn_string start_time = getChildNodeText( p_task, "Start" );
            kn_string end_time   = getChildNodeText( p_task, "Finish" );

            if(m_is_nplan_format)//NPlan导出的扩展MS Project格式
            {
                action.setPlanDays( getChildNodeValue( p_task, "PlanDays" ) );
                action.setPlanHours( getChildNodeValue( p_task, "PlanHours" ) );
				action.setDifficulty( getChildNodeValue( p_task, "Difficulty" ) );
            }

            calcTimeInterval( start_time, end_time, days, hours );

            action.setPlanDays( days );
            action.setPlanHours( hours );
            action.setStartTime( start_time.c_str() );
            action.setEndTime( end_time.c_str() );

            int done_precent = getChildNodeValue( p_task, "PercentComplete" );
            done_precent = calcActionStateByPercent(done_precent);

            action.setState( done_precent );

            task.addTaskCard( action );
        }

        if( 1 == getChildNodeValue( p_task, "Milestone" ))
        {
            if ( outline_level == level )
            {
                milestone.setName( task.getName().c_str());
                milestone.setMemo( task.getTaskDescribe().c_str());
            }
            else
            {
                milestone.setName( action.getName().c_str());
            }

            milestone.setId( 0 ); //force to auto calc
            m_pPrjData->addMilestone( milestone );
        }
    }

    if( !task.getName().empty())
    {
        m_pPrjData->addTask( task );
    }

    return _result;
}

//解析任务分配,将taskID转化为resourceID
bool CNProjectMPPXMLData:: parseAssignment()
{
    bool _result = false;

    if( NULL == m_p_root )
    {
        return _result;
    }

    TiXmlElement* p_assigns = m_p_root->FirstChildElement( "Assignments" );
    if( NULL == p_assigns )
    {
        return _result;
    }

    TiXmlElement* p_assign = p_assigns->FirstChildElement( "Assignment" );
    if( NULL == p_assign )
    {
        return _result;
    }

    _result = true;

    CNProjectTask_LST::iterator task_iter;

    CNProjectTask_LST& list_tasks = m_pPrjData->getTasks();

    for(; p_assign != NULL; p_assign = p_assign->NextSiblingElement())
    {
        int task_id = getChildNodeValue( p_assign, "TaskUID" );
        int res_id  = getChildNodeValue( p_assign, "ResourceUID" );

        for( task_iter = list_tasks.begin(); task_iter != list_tasks.end(); task_iter++ )
        {
            CNProjectTaskCard_LST& list_cards  = task_iter->getTaskCards();
            CNProjectTaskCard_LST::iterator it = find( list_cards.begin(), list_cards.end(), task_id );
            if( it != list_cards.end())
            {
                it->setLeaderId( res_id );
            }
        }
    }

    return _result;
}

bool CNProjectMPPXMLData::save_all_resource( TiXmlElement* p_resources )
{
    bool _result = false;

    if((NULL == m_pPrjData) || (NULL == p_resources))
    {
        return _result;
    }

    typedef std::vector <CNProjectResource> VectResource;

    CNProjectResourcePool &ResPool = m_pPrjData->getResourcePool();

    VectResource &v_Res = ResPool.getResources();

    char szBuff[32] = {0};

    VectResource::iterator it_res = v_Res.begin();
    for (; it_res != v_Res.end(); ++it_res )
    {
        TiXmlElement* p_resource = add_node( NULL, "Resource", NULL );
        if( p_resource )
        {
            sprintf( szBuff, "%d", it_res->getId());

            add_node( p_resource, "UID", szBuff );
            add_node( p_resource, "ID", szBuff );
            kn_string wstrName = it_res->getName();
            add_node( p_resource, "Name", wstrName);
            res_type res_type = it_res->getType();

            switch (res_type)
            {
            case res_man:
            case res_woman:
                add_node( p_resource, "Type", "1" ); //对应Project中的工时
                break;
            case res_device:
                add_node( p_resource, "Type", "0" ); //对应Project中的材料
                break;
            default:
                break;
            }

            p_resources->LinkEndChild(p_resource);
        }
    }

    return _result;
}

void CNProjectMPPXMLData::save_assignment(TiXmlElement* assignments, ptime &action_stime, ptime &action_etime, vector<kn_uint> &vect_hours, CNProjectTaskCard_LST::iterator iter_taskcard, const string& str_uid)
{
    if(assignments==NULL)
    { //预防性编码，调用时控制了参数的有效性
        return;
    }

	CNProjectCalendar& calendar = m_pPrjData->getCalendar();

    TiXmlElement* assignment = add_node( assignments, "Assignment", NULL );
    if( assignment )
    {
        add_node( assignment, "UID", str_uid.c_str() );
        add_node( assignment, "TaskUID", str_uid.c_str() );

        if(iter_taskcard->getLeaderId() < 1)
        {	//未分配任务
            add_node( assignment, "ResourceUID", "-65535" );
        }
        else
        {
            char szBuff[32]={0};
            sprintf( szBuff, "%d", iter_taskcard->getLeaderId());
            add_node( assignment, "ResourceUID", szBuff );
        }

		ptime action_time;
		date action_date;
		time_duration action_td;
		boost::gregorian::days one_day( 1 );

		const size_t st_count = vect_hours.size();
		for(size_t i = 0; i < st_count; i++)
		{
			TiXmlElement* date = add_node(assignment, "TimephasedData", NULL);
			add_node( date, "Type", "1" );
			add_node( date, "UID", str_uid.c_str() );

			if(0 == i)
			{
				action_time = action_stime;
			}
			else
			{
				action_td = calendar.getWorkingTime();
				action_time = ptime( action_date, action_td );
			}
			string str_time = ptime2str ( action_time, true ) ;
			add_node ( date, "Start", str_time.c_str() );

			if(st_count-1 == i)
			{
				action_time = action_etime;
			}
			else
			{
				action_td = calendar.getClosingTime();
				action_time = ptime( action_date, action_td );
			}

			str_time = ptime2str( action_time, true);
			add_node( date, "Finish", str_time.c_str() );

			add_node( date, "Unit", "2" );

			if(0 < vect_hours[i] )
			{
				char szBuff[32]={0};
				sprintf( szBuff, "PT%dH0M0S", vect_hours[i] );
				add_node( date, "Value", szBuff );
			}

			action_date += one_day;
		}
    }
}

bool CNProjectMPPXMLData::save_all_task( TiXmlElement* tasks, TiXmlElement* assignments )
{
    bool _result = false;

    if((NULL == m_pPrjData) || (NULL == tasks) || (NULL == assignments))
    {
        return _result;
    }

    CNProjectTask_LST* p_v_task = m_pPrjData->getpTasks();
    if( p_v_task == NULL )
    {
        return _result;
    }

    ptime time_begin = m_pPrjData->getProBeginTime();
    ptime time_end = m_pPrjData->getProEndTime();

    string prj_start_time = ptime2str(time_begin, true );
    string prj_end_time = ptime2str(time_end, true );

    kn_string strName = m_pPrjData->getName();
    kn_string strPrjData = m_pPrjData->getProDescribe();

    TiXmlElement* task = add_node( tasks, "Task", NULL );
    if( task )
    {
        add_node( task, "UID", "0" );//MPP中非显示对象
        add_node( task, "ID", "0" );
        add_node( task, "Name", strName);
        add_node( task, "WBS", "0" );
        add_node( task, "OutlineNumber", "0" );
        add_node( task, "OutlineLevel", "0" );
        add_node( task, "Start", prj_start_time.c_str());
        add_node( task, "Finish", prj_end_time.c_str());
        add_node( task, "ConstraintType", "0" ); //不加此字段，时间显示会混乱
        add_node( task, "Notes", strPrjData); //项目备注
    }

    task = add_node( tasks, "Task", NULL );
    if( task )
    {
        //一级节点
        add_node( task, "UID", "1" );
        add_node( task, "ID", "1" );
        add_node( task, "Name", m_pPrjData->getName() ); //项目名称
        add_node( task, "WBS", "1" );
        add_node( task, "OutlineNumber", "1" );
        add_node( task, "OutlineLevel", "1" );
        add_node( task, "Start", prj_start_time.c_str());
        add_node( task, "Finish", prj_end_time.c_str());
        add_node( task, "ConstraintType", "0" ); //不加此字段，时间显示会混乱
    }

    UINT uid( 2 ), level1_id(1);
    char szBuff[32]     = {0};
    char szWBSBuff[256] = {0};

    string str_wbs;

	CNProjectCalendar& calendar = m_pPrjData->getCalendar();

	CNProjectTask_LST::iterator iter_task;
    for ( iter_task = p_v_task->begin(); iter_task != p_v_task->end(); ++iter_task )
    {
        TiXmlElement* task = add_node( tasks, "Task", NULL );
        if( task == NULL )
        {
            continue;
        }

        //二级节点
        memset( szBuff, 0, sizeof(char)*32 );
        sprintf( szBuff, "%d", uid++ );
        add_node( task, "UID", szBuff );
        add_node( task, "ID", szBuff );
        add_node( task, "Name", iter_task->getName());

        memset( szWBSBuff, 0, sizeof(char)*256 );
        sprintf( szWBSBuff, "1.%s", szBuff ); //目前WBS从1.2开始编号，但不影响显示，所以暂不修改
        add_node( task, "WBS", szWBSBuff );
        str_wbs = szWBSBuff;
        add_node( task, "OutlineNumber", szWBSBuff );
        add_node( task, "OutlineLevel", "2" );  //NPlan都只支持二级格式

        string start_time = ptime2str ( iter_task->getStartTime(), true );
        string end_time = ptime2str ( iter_task->getEndTime(), true );
        add_node( task, "Start", start_time.c_str());
        add_node( task, "Finish", end_time.c_str());
        add_node( task, "Estimated", "1" );
        add_node( task, "ConstraintType", "0" ); //不加此字段，时间显示会混乱

        kn_string str = iter_task->getTaskDescribe();
        if( !str.empty())
        {
            add_node( task, "Notes", str );
        }

        CNProjectTaskCard_LST &lst_cards = iter_task->getTaskCards();
        CNProjectTaskCard_LST::iterator iter_taskcard;

        size_t action_count = lst_cards.size();

        int index( 1 );
        for ( iter_taskcard = lst_cards.begin(); iter_taskcard != lst_cards.end(); iter_taskcard++ )
        {
            TiXmlElement* task = add_node( tasks, "Task", NULL );
            if( task == NULL )
            {
                continue;
            }

            //三级节点
            memset( szBuff, 0, sizeof(char)*32 );
            sprintf( szBuff, "%d", uid++ );

            const string str_uid = szBuff;
            add_node( task, "UID", szBuff );
            add_node( task, "ID", szBuff );
            add_node( task, "Name", iter_taskcard->getName());

            memset( szWBSBuff, 0, sizeof(char)*256 );
            sprintf( szWBSBuff, "%s.%d", str_wbs.c_str(), index );
            add_node( task, "WBS", szWBSBuff );
            add_node( task, "OutlineNumber", szWBSBuff );
            add_node( task, "OutlineLevel", "3" );

            ptime action_stime, action_etime;
			action_stime = iter_taskcard->getStartTime();
			action_etime = iter_taskcard->getEndTime();

			if( !action_stime.is_not_a_date_time() )
			{
				time_duration action_td = action_stime.time_of_day();
				if( (action_td.hours() == 0) && (action_td.minutes() == 0) && (action_td.seconds() == 0) )
				{  //未填写时间，开始时间默认为工作日的开始上班时间
					action_stime += calendar.getWorkingTime();
				}
			}

			if( !action_etime.is_not_a_date_time() )
			{
				time_duration action_td = action_etime.time_of_day();
				if( (action_td.hours() == 0) && (action_td.minutes() == 0) && (action_td.seconds() == 0) )
				{
					//未填写时间，线束时间默认为工作日的结束上班时间
					action_etime += calendar.getClosingTime();
				}
			}

			string str_start_time = ptime2str( action_stime, true );
			string str_end_time = ptime2str( action_etime, true );

			add_node ( task, "Start", str_start_time.c_str() );
			add_node ( task, "Finish", str_end_time.c_str() );

			//NPlan导出的扩展MS Project格式
			int days = iter_taskcard->getPlanDays();
			int hours = iter_taskcard->getPlanHours();
			ostringstream oss;
			oss << days;
			add_node ( task, "PlanDays", oss.str().c_str() );
			oss.str("");

			oss << hours;
			add_node ( task, "PlanHours", oss.str().c_str() );
			oss.str("");

			oss << iter_taskcard->getDifficulty();
			add_node ( task, "Difficulty", oss.str().c_str() );
			oss.str("");

			vector<kn_uint> vect_hours = calendar.getWorkHours(action_stime , action_etime);
			const kn_uint work_hours = std::accumulate(vect_hours.begin(), vect_hours.end(), 0);
			oss << "PT" << work_hours << "H0M0S";

			float actual_work_hours = work_hours;
            string str_precent = "0";
            int state = iter_taskcard->getState();
            switch(state)
            {
            case 0:
                str_precent = "0";
				actual_work_hours = 0;
                break;
            case 1:
                str_precent = "40";
				actual_work_hours *= 0.4;
                break;
            case 2:
                str_precent = "80";
				actual_work_hours *= 0.8;
                break;
			case 3:
				str_precent = "100";
				add_node ( task, "ActualFinish", str_end_time.c_str() );
				break;
            default:
                break;
            }

			//add_node ( task, "PercentWorkComplete", str_precent.c_str() ); //写入也无效，PROJECT会重新计算
			add_node ( task, "ActualStart", str_start_time.c_str() );

			//Percent Work Complete = (Actual Work / Work) * 100
			add_node ( task, "Work", oss.str().c_str() );
			oss.str("");

			const int i_act_work = actual_work_hours;
			const int i_act_work_minutes = (actual_work_hours - i_act_work) * 60;
			oss << "PT" << i_act_work <<  "H" << i_act_work_minutes << "M0S";

			add_node ( task, "ActualWork", oss.str().c_str() );
			add_node ( task, "ActualDuration", oss.str().c_str() );
			oss.str("");

			add_node( task, "Estimated", "1" );
			//不加此字段，时间显示会混乱
            (index == 1) ? add_node( task, "ConstraintType", "4" ):add_node( task, "ConstraintType", "6" );

            //assignment
            save_assignment(assignments, action_stime, action_etime , vect_hours ,iter_taskcard, str_uid);

            index++ ;
        }
    }

    return _result;
}

void CNProjectMPPXMLData::save_calendars()
{
    //TODO:目前无此项数据，仅写入DummyNODE
    TiXmlElement* calendars = add_node ( m_p_root, "Calendars", NULL );
    TiXmlElement* calendar = add_node ( calendars, "Calendar", NULL );
    add_node ( calendar, "UID", "1" );
    add_node ( calendar, "Name", kn_string(_T("标准")) );
    add_node ( calendar, "IsBaseCalendar", "1" );
    add_node ( calendar, "BaseCalendarUID", "-1" );
    TiXmlElement* weekdays = add_node ( calendar, "WeekDays", NULL );

    for ( int i = 1; i <= 7; i++ ) //默认星期日为每周第一天
    {
        TiXmlElement* weekday = add_node ( weekdays, "WeekDay", NULL );

        char szBuff[12] = {0};
        sprintf ( szBuff, "%d", i );
        add_node ( weekday, "DayType", szBuff );

        if ( ( i == 1 ) || ( i == 7 ) )
        {
            add_node ( weekday, "DayWorking", "0" ); //休息日
        }
        else
        {
            add_node ( weekday, "DayWorking", "1" );

            TiXmlElement* workingtimes = add_node ( weekday, "WorkingTimes", NULL );

            TiXmlElement* workingtime = add_node ( workingtimes, "WorkingTime", NULL );
            add_node ( workingtime, "FromTime", "09:00:00" );
            add_node ( workingtime, "ToTime", "12:00:00" );

            workingtime = add_node ( workingtimes, "WorkingTime", NULL );
            add_node ( workingtime, "FromTime", "13:00:00" );
            add_node ( workingtime, "ToTime", "18:00:00" );
        }
    }
}

int CNProjectMPPXMLData:: save( kn_string &filename )
{
    TiXmlDocument doc;

    TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", "yes" );

    if( decl )
    {
        doc.LinkEndChild( decl );
    }

    m_p_root = new TiXmlElement( "Project" );
    if( !m_p_root )
    {
        return ERROR_FUNCTION_FAILED;
    }

    m_p_root->SetAttribute( "xmlns", "http://schemas.microsoft.com/project" );

    size_t pos = filename.find_last_of( '/' );
    if( kn_string::npos != pos )
    {
        kn_string file = filename.substr( pos+1 );
        add_node( m_p_root, "Name", file );
    }

    add_node( m_p_root, "SaveVersion", "12" );
    add_node( m_p_root, "Title", "NPlan Export" );
    add_node( m_p_root, "Manager", m_pPrjData->getLeader());

	string prj_start_time = ptime2str( m_pPrjData->getProBeginTime(), true );
    string prj_end_time = ptime2str( m_pPrjData->getProEndTime(), true );
	add_node( m_p_root, "StartDate", prj_start_time.c_str() );
	add_node( m_p_root, "FinishDate",  prj_end_time.c_str() );

	CNProjectCalendar& calendar = m_pPrjData->getCalendar();

	time_duration default_start_time = calendar.getWorkingTime();
	string start_time = to_simple_string(default_start_time);

	time_duration default_end_time = calendar.getClosingTime();
	string end_time = to_simple_string(default_end_time);

	add_node( m_p_root, "DefaultStartTime", start_time.c_str() );
    add_node( m_p_root, "DefaultFinishTime", end_time.c_str() );

    add_node( m_p_root, "MinutesPerDay", "480" );
    add_node( m_p_root, "MinutesPerWeek", "2400" );
    add_node( m_p_root, "DaysPerMonth", "20" ); //TODO

    add_node( m_p_root, "NPlan", "1" ); //标识此文件格式为NPlan导出的扩展格式
    add_node( m_p_root, "ProjectExternallyEdited", "0" );

    save_calendars();

    //先不挂在父节点上，数据设置完毕后，最后将其挂在父节点上就行了
    TiXmlElement* assignments = add_node( NULL, "Assignments", NULL );

    TiXmlElement* tasks = add_node( m_p_root, "Tasks", NULL );
    if(tasks)
    {
        save_all_task( tasks, assignments );
    }

    TiXmlElement* p_resources = add_node( NULL, "Resources", NULL );
    if(p_resources)
    {
        save_all_resource( p_resources );
        m_p_root->LinkEndChild( p_resources );
    }

    if(assignments)
    {
        m_p_root->LinkEndChild( assignments ); //Assignments
    }

    doc.LinkEndChild( m_p_root );

    if ( !doc.SaveFile( ns2s( filename ).c_str()))
    {
        return ERROR_CREATE_FAILED;
    }

    return NO_ERROR;
}


text:
///////////////////////////////////////////////////////////////////////////////
// accesss.hpp
//
//  Copyright 2004 Eric Niebler. Distributed under the Boost
//  Software License, Version 1.0. (See accompanying file
//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_XPRESSIVE_DETAIL_CORE_ACCESS_HPP_EAN_10_04_2005
#define BOOST_XPRESSIVE_DETAIL_CORE_ACCESS_HPP_EAN_10_04_2005

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

#include <vector>
#include <boost/xpressive/detail/detail_fwd.hpp>
#include <boost/xpressive/detail/dynamic/matchable.hpp>

namespace boost { namespace xpressive { namespace detail
{

///////////////////////////////////////////////////////////////////////////////
// core_access
//
template<typename BidiIter>
struct core_access
{
    // BUGBUG give basic_regex move semantics!
    static basic_regex<BidiIter> make_regex(regex_impl<BidiIter> const &impl)
    {
        return basic_regex<BidiIter>(impl);
    }

    static std::size_t get_hidden_mark_count(basic_regex<BidiIter> const &rex)
    {
        return rex.impl_->hidden_mark_count_;
    }

    static bool invalid(basic_regex<BidiIter> const &rex)
    {
        return rex.invalid_();
    }

    static bool match(basic_regex<BidiIter> const &rex, state_type<BidiIter> &state)
    {
        return rex.match_(state);
    }

    static shared_ptr<detail::regex_impl<BidiIter> > const &
    get_regex_impl(basic_regex<BidiIter> const &rex)
    {
        return rex.impl_.get();
    }

    static void init_sub_match_vector
    (
        sub_match_vector<BidiIter> &subs_vect
      , sub_match_impl<BidiIter> *subs_ptr
      , std::size_t size
    )
    {
        subs_vect.init_(subs_ptr, size);
    }

    static void init_sub_match_vector
    (
        sub_match_vector<BidiIter> &subs_vect
      , sub_match_impl<BidiIter> *subs_ptr
      , std::size_t size
      , sub_match_vector<BidiIter> const &that
    )
    {
        subs_vect.init_(subs_ptr, size, that);
    }

    static void init_match_results
    (
        match_results<BidiIter> &what
      , regex_id_type regex_id
      , sub_match_impl<BidiIter> *sub_matches
      , std::size_t size
    )
    {
        what.init_(regex_id, sub_matches, size);
    }

    static sub_match_vector<BidiIter> &get_sub_match_vector(match_results<BidiIter> &what)
    {
        return what.sub_matches_;
    }

    static sub_match_impl<BidiIter> *get_sub_matches(sub_match_vector<BidiIter> &subs)
    {
        return subs.sub_matches_;
    }

    static results_extras<BidiIter> &get_extras(match_results<BidiIter> &what)
    {
        return what.get_extras_();
    }

    static nested_results<BidiIter> &get_nested_results(match_results<BidiIter> &what)
    {
        return what.nested_results_;
    }

    static action_state &get_action_state(match_results<BidiIter> &what)
    {
        return what.action_state_;
    }

    static void set_prefix_suffix(match_results<BidiIter> &what, BidiIter begin, BidiIter end)
    {
        what.set_prefix_suffix_(begin, end);
    }

    static void reset(match_results<BidiIter> &what)
    {
        what.reset_();
    }

    static void set_base(match_results<BidiIter> &what, BidiIter base)
    {
        what.set_base_(base);
    }
};

}}} // namespace boost::xpressive::detail

#endif

max_stars_repo_name: dstrigl/mcotf

max_issues_repo_name: dstrigl/mcotf

max_forks_repo_name: dstrigl/mcotf


text:
#include <geometry.h>
#include <tiny.h>

#define BOOST_AUTO_TEST_MAIN
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/floating_point_comparison.hpp>
#include <boost/test/test_tools.hpp>

typedef tiny::MathTypes<float> MT;
typedef MT::quaternion_type    Q;
typedef MT::vector3_type       V;
typedef MT::real_type          T;
typedef MT::value_traits       VT;

BOOST_AUTO_TEST_SUITE(geometry);

BOOST_AUTO_TEST_CASE(overlap_obb_obb_test)
{
  // touching bottom-top faces
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(0.0, -2.0, 0.0);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Ry(VT::pi_quarter());

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(test1);
    BOOST_CHECK(test2);
  }
  // touching left-right faces
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(2.0, 0.0, 0.0);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Rx(VT::pi_quarter());

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(test1);
    BOOST_CHECK(test2);
  }
  // touching front-back faces
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(0.0, 0.0, 2.0);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Rz(VT::pi_quarter());

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(test1);
    BOOST_CHECK(test2);
  }
  // separating bottom-top faces
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(0.0, -2.1, 0.0);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Ry(VT::pi_quarter());

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(!test1);
    BOOST_CHECK(!test2);
  }
  // separating left-right faces
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(2.1, 0.0, 0.0);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Rx(VT::pi_quarter());

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(!test1);
    BOOST_CHECK(!test2);
  }
  // separating front-back faces
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(0.0, 0.0, 2.1);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Rz(VT::pi_quarter());

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(!test1);
    BOOST_CHECK(!test2);
  }
  // A inside of B
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(0.5, 0.5, 0.5);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(0.0, 0.0, 0.0);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Ry(VT::pi_quarter());

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(test1);
    BOOST_CHECK(test2);
  }
  // B inside of A
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(0.0, 0.0, 0.0);
    V const half_extB = V::make(0.5, 0.5, 0.5);
    Q const qB        = Q::Ry(VT::pi_quarter());

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(test1);
    BOOST_CHECK(test2);
  }
  // touching edge-edge-case
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(2.0, 2.0, 0.0);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Ru(VT::pi_half(), centerB );

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(test1);
    BOOST_CHECK(test2);
  }
  // separating edge-edge-case
  {
    V const centerA   = V::make(0.0, 0.0, 0.0);
    V const half_extA = V::make(1.0, 1.0, 1.0);
    Q const qA        = Q::identity();

    geometry::OBB<MT> obbA = geometry::make_obb<MT>(centerA, qA, half_extA);

    V const centerB   = V::make(2.01, 2.01, 0.0);
    V const half_extB = V::make(1.0, 1.0, 1.0);
    Q const qB        = Q::Ru(VT::pi_half(), centerB );

    geometry::OBB<MT> obbB = geometry::make_obb<MT>(centerB, qB, half_extB);

    bool const test1 = geometry::overlap_obb_obb(obbA,obbB);
    bool const test2 = geometry::overlap_obb_obb(obbB,obbA);

    BOOST_CHECK(!test1);
    BOOST_CHECK(!test2);
  }

}

BOOST_AUTO_TEST_SUITE_END();

max_stars_repo_name: diku-dk/PROX

max_issues_repo_name: erleben/matchstick

max_forks_repo_name: erleben/matchstick


text:
#include <boost/bind.hpp>
#include <iostream>
#include "server.h"

using namespace boost::asio;
using namespace boost::asio::ip;

namespace tcp_boost
{
    server::server()
        : m_ios(),
          m_acceptor(nullptr)
    {

    }

    server::~server()
    {
        m_ios.post(boost::bind(&server::do_close, this));
    }

    void
    server::start(unsigned short port)
    {
        tcp::endpoint endpoint(tcp::v4(), port);
        m_acceptor = new tcp::acceptor(m_ios, endpoint);

        // Disable 'linger' behaviour to avoid problem when reusing the same port.
        m_acceptor->set_option(tcp::acceptor::reuse_address(true));

        m_listening_port = m_acceptor->local_endpoint().port();

        // Start server thread.
        m_thread = boost::thread(boost::bind(&io_service::run, &m_ios));

        // Start client listeneing.
        m_ios.post(boost::bind(&server::begin_accept, this));

        std::cout << "Start server. Port : " + std::to_string(m_listening_port) +"\n";
    }

    session*
    server::create_new_session(io_service &ios)
    {
        return new session(ios);
    }

    unsigned short
    server::get_listening_port() const
    {
        return m_listening_port;
    }

    io_service&
    server::get_io_service()
    {
        return m_ios;
    }

    void
    server::begin_accept()
    {
        auto cl_session = create_new_session(m_ios);
        m_acceptor->async_accept(cl_session->get_socket(),
                boost::bind(&server::handle_accept, this, cl_session,
                    boost::asio::placeholders::error));
    }

    void
    server::handle_accept(session *cl_session, const boost::system::error_code &error)
    {
        if (error)
        {
            std::cout << "Failed to accept new client. : " + error.message() + "\n";
        }
        else
        {
            std::cout << "New client connected.\n";
            cl_session->start();
        }

        // Continue to listen next client.
        begin_accept();
    }

    void
    server::do_close()
    {
        m_acceptor->close();
        delete m_acceptor;
    }
}

max_stars_repo_name: chickeningot/tcp-boost

max_issues_repo_name: chickeningot/tcp-boost

max_forks_repo_name: chickeningot/tcp-boost


text:
#pragma once

#include <logos/request/transaction.hpp>
#include <logos/node/utility.hpp>
#include <logos/lib/utility.hpp>
#include <logos/lib/numbers.hpp>
#include <logos/common.hpp>

#include <boost/property_tree/ptree.hpp>

enum class RequestType : uint8_t
{
    // Native Logos Requests
    //
    Send               = 0,
    Proxy              = 1,
    Issuance           = 2,

    // Administrative Token
    // Requests
    //
    IssueAdditional   = 3,
    ChangeSetting     = 4,
    ImmuteSetting     = 5,
    Revoke            = 6,
    AdjustUserStatus  = 7,
    AdjustFee         = 8,
    UpdateIssuerInfo  = 9,
    UpdateController  = 10,
    Burn              = 11,
    Distribute        = 12,
    WithdrawFee       = 13,
    WithdrawLogos     = 14,

    // Token User Requests
    //
    TokenSend         = 15,

    //Election Requests
    ElectionVote      = 16,
    AnnounceCandidacy = 17,
    RenounceCandidacy = 18,
    StartRepresenting = 19,
    StopRepresenting  = 20,
    Stake             = 21,
    Unstake           = 22,

    // Reward Requests
    //
    Claim             = 24,

    // Unknown
    //
    Unknown           = 23
};

class Reservations;

struct Request
{
    using BlockHash      = logos::block_hash;
    using AccountAddress = logos::uint256_union;

    struct Locator
    {
        Locator() = default;

        Locator(bool & error,
                logos::stream & stream);

        uint64_t Serialize(logos::stream & stream);

        BlockHash hash  = 0;
        uint16_t  index = 0;
    };

    Request() = default;

    Request(RequestType type);

    Request(RequestType type,
            const AccountAddress & origin,
            const BlockHash & previous,
            const Amount & fee,
            uint32_t sequence);

    Request(RequestType type,
            const AccountAddress & origin,
            const BlockHash & previous,
            const Amount & fee,
            uint32_t sequence,
            const AccountSig & signature);

    Request(bool & error,
            const logos::mdb_val & mdbval);

    Request(bool & error,
            logos::stream & stream);

    Request(bool & error,
            boost::property_tree::ptree const & tree);

    virtual ~Request() = default;

    virtual logos::AccountType GetAccountType() const;
    virtual logos::AccountType GetSourceType() const;

    /// This method returns the account that will
    /// own the request. Eg. For TokenSend requests
    /// this will be the origin, but for Revoke
    /// requests, this will be the token account.
    /// @return The address of the owning account.
    virtual AccountAddress GetAccount() const;

    /// This method returns the account from which
    /// an amount is being deducted. For most accounts
    /// this will be the origin, but for Revoke
    /// commands, this is not the case.
    /// @return The address of the source account.
    virtual AccountAddress GetSource() const;

    virtual Amount GetLogosTotal() const;
    virtual Amount GetTokenTotal() const;

    void Sign(AccountPrivKey const & priv);
    void Sign(AccountPrivKey const & priv, AccountPubKey const & pub);
    void SignAndHash(bool & error, boost::property_tree::ptree const & ptree);
    bool VerifySignature(AccountPubKey const & pub) const;

    std::string ToJson() const;
    uint64_t ToStream(logos::stream & stream, bool with_work = false) const;
    logos::mdb_val ToDatabase(std::vector<uint8_t> & buf, bool with_work = false) const;
    virtual void DeserializeDB(bool & error, logos::stream & stream);

    virtual boost::property_tree::ptree SerializeJson() const;
    uint64_t DoSerialize(logos::stream & stream) const;
    virtual uint64_t Serialize(logos::stream & stream) const;
    void Deserialize(bool & error, logos::stream & stream);

    virtual bool Validate(logos::process_return & result,
                          std::shared_ptr<logos::Account> info) const;
    virtual bool Validate(logos::process_return & result) const;

    virtual BlockHash GetHash () const;
    BlockHash Hash() const;
    virtual void Hash(blake2b_state & hash) const;

    virtual uint16_t WireSize() const;

    virtual bool operator==(const Request & other) const;

    static const uint8_t MAX_TRANSACTIONS = 8;

    RequestType       type = RequestType::Unknown;
    AccountAddress    origin;
    BlockHash         previous;
    Amount            fee;
    uint32_t          sequence = 0;
    AccountSig        signature;
    uint64_t          work     = 0;
    BlockHash         next;
    mutable Locator   locator;
    mutable BlockHash digest;
};

struct Send : Request
{
    using Request::Hash;

    using Transaction  = ::Transaction<Amount>;
    using Transactions = std::vector<Transaction>;

    Send ();

    /// Class constructor
    /// Note that if additional transaction is added after construction, the StateBlock must be re-signed
    /// @param account the account creating the StateBlock
    /// @param previous the hash of the previous StateBlock on the account's send chain
    /// @param sequence the sequence number
    /// @param to the target account, additional targets can be added with AddTransaction()
    /// @param amount the transaction amount, additional amounts can be added with AddTransaction()
    /// @param transaction_fee the transaction fee
    /// @param priv the private EdDSA key of the account
    /// @param pub the public EdDSA key of the account
    /// @param work the prove of work
    Send ( AccountAddress const & account,
           BlockHash const & previous,
           uint32_t sequence,
           AccountAddress const & to,
           Amount const & amount,
           Amount const & transaction_fee,
           AccountPrivKey const & priv,
           AccountPubKey const & pub);

    /// Class constructor
    /// Note that if additional transaction is added after construction, the StateBlock must be re-signed
    /// @param account the account creating the StateBlock
    /// @param previous the hash of the previous StateBlock on the account's send chain
    /// @param sequence the sequence number
    /// @param to the target account, additional targets can be added with AddTransaction()
    /// @param amount the transaction amount, additional amounts can be added with AddTransaction()
    /// @param transaction_fee the transaction fee
    /// @param sig the EdDSA signature of the StateBlock
    /// @param work the prove of work
    Send ( AccountAddress const & account,
           BlockHash const & previous,
           uint32_t sequence,
           AccountAddress const & to,
           Amount const & amount,
           Amount const & transaction_fee,
           AccountSig const & sig);

    /// Class constructor
    /// construct from deserializing a property_tree which was decoded from a Json string
    /// @param error it will be set to true if deserialization fail [out]
    /// @param tree the property_tree to deserialize from
    /// @param with_batch_hash if the property_tree should contain the batch_hash
    /// @param with_work if the property_tree should contain the prove of work
    Send(bool & error,
         const boost::property_tree::ptree & tree);

    /// Constructor from deserializing a buffer read from the database
    /// @param error it will be set to true if deserialization fail [out]
    /// @param mdbval the buffer read from the database
    Send(bool & error,
         const logos::mdb_val & mdbval);

    /// Class constructor
    /// construct from deserializing a stream which was decoded from a Json string
    /// @param error it will be set to true if deserialization fail [out]
    /// @param stream the stream containing serialized data [in]
    /// @param with_batch_hash if the serialized data should have the batch_hash [in]
    Send (bool & error,
          logos::stream & stream);

    Amount GetLogosTotal() const override;

    /// Add a new transaction
    /// @param to the target account
    /// @param amount the transaction amount
    /// @returns if the new transaction is added.
    bool AddTransaction(const AccountAddress & to, const Amount & amount);
    bool AddTransaction(const Transaction & transaction);

    /// Add the data members to a hash context
    /// @param hash the hash context
    void Hash(blake2b_state & hash) const override;

    /// Get the send request hash without re-computing it
    /// @returns the hash value
    BlockHash GetHash () const override;

    /// Serialize the data members to a property_tree which will be encoded to Json
    /// @param tree the property_tree to add data members to
    /// @param with_batch_hash if batch_hash should be serialized
    /// @param with_work if prove of work should be serialized
    boost::property_tree::ptree SerializeJson() const override;

    /// Serialize the data members to a stream
    /// @param stream the stream to serialize to
    /// @returns the number of bytes serialized
    uint64_t Serialize (logos::stream & stream) const override;
    void Deserialize(bool & error, logos::stream & stream);
    void DeserializeDB(bool &error, logos::stream &stream) override;

    bool operator==(const Request & other) const override;

    Transactions      transactions;
};

max_stars_repo_name: LogosNetwork/logos-core

max_issues_repo_name: LogosNetwork/logos-core

max_forks_repo_name: LogosNetwork/logos-core


text:
/*
    Copyright (c) 2010 Séverin Lemaignan (slemaign@laas.fr)

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version
    3 of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <boost/foreach.hpp>
#include <boost/functional/hash.hpp>

#include <algorithm>

#include "macros.h"
#include "constants.h"

#include "memoryview.h"
#include "graph.h"
#include "node.h"
#include "node_relation.h"

using namespace std;
using namespace boost;

/** A simple boolean function that returns true for characters that are not
  "safe" (currently in the sense of GraphViz names.
**/
bool safeIdFilter(char c) {
    return c=='-' || c==':' || c=='_';
}

Node::Node(int id, const string& label, const Node* neighbour) :
    id(id),
    safeid(to_string(id)),
    label(label),
    renderer(NodeRenderer(id, label)),
    _selected(false),
    decayTime(0.0),
    decaySpeed(1.0),
    decaying(true),
    distance_to_selected(-1),
    distance_to_selected_updated(false),
    base_charge(INITIAL_CHARGE),
    charge(INITIAL_CHARGE)
{

    safeid.resize(std::remove_if(safeid.begin(), safeid.end(), safeIdFilter) - safeid.begin());

    //If a neighbour is given, we set our initial position close to it.
    if (neighbour)
        pos = neighbour->pos + vec2f(10.0 * (float)rand()/RAND_MAX - 5 , 10.0 * (float)rand()/RAND_MAX - 5);
    else
        pos = vec2f(100.0 * (float)rand()/RAND_MAX - 50 , 100 * (float)rand()/RAND_MAX - 50);

    speed = vec2f(0.0, 0.0);

    mass = INITIAL_MASS;
    damping = INITIAL_DAMPING;

}

bool Node::operator< (const Node& node2) const {
    return id < node2.getID();
}

const string& Node::getSafeID() const {
    return safeid;
}

void Node::setColour(vec4f col) {
    renderer.setColour(col);
}

std::vector<NodeRelation>& Node::getRelations() {
    return relations;
}

vector<Node*>  Node::getConnectedNodes(){
    vector<Node*> res;

    for(auto& rel : relations) {
        if (rel.to == this)
            res.push_back(rel.from);
        else
            res.push_back(rel.to);
    }
    return res;
}

bool Node::isConnectedTo(Node* node) {
    for(auto& rel : relations) {
        if (rel.to == node || rel.from == node)
            return true;
    }
    return false;
}

NodeRelation& Node::addRelation(Node& to) {

    vector<const NodeRelation*> rels = getRelationTo(to);

    relations.push_back(NodeRelation(this, &to)); //Add a new relation

    if (!to.isConnectedTo(this)){
        to.addRelation(*this);
    }

    TRACE("Added relation from " << label << " to " << to.label);

    return relations.back();

}

vector<const NodeRelation*> Node::getRelationTo(Node& node) const {

    vector<const NodeRelation*> res;

    for(const auto& rel : relations) {
        if (rel.to == &node)
            res.push_back(&rel);
    }
    return res;
}

void Node::updateKineticEnergy() {
    kinetic_energy = mass * speed.length2();
}

void Node::step(Graph& g, float dt){

    TRACE("Updating " << label << " color based on activity");
    if (activity > 0)
        setColour(vec4f(activity + 0.1, activity * 0.5 + 0.1, 0.1, 1.0));
    else
        setColour(vec4f(0.1,0.1, -activity + 0.1, 1.0));

    /** Compute here the new position of the node **/

    TRACE("Stepping for node " << label);
    vec2f force = vec2f(0.0, 0.0);

    // Algo from Wikipedia -- http://en.wikipedia.org/wiki/Force-based_layout

    coulombForce = g.coulombRepulsionFor(*this);
    force +=coulombForce;

    hookeForce = g.hookeAttractionFor(*this);
    force += hookeForce;

    TRACE("** Total force applying: Fx=" << force.x << ", Fy= " << force.y);

    speed = (speed + force * dt) * damping;
    speed.x = CLAMP(speed.x, -MAX_SPEED, MAX_SPEED);
    speed.y = CLAMP(speed.y, -MAX_SPEED, MAX_SPEED);

    updateKineticEnergy();

    //Check we have enough energy to move :)
    if (kinetic_energy > MIN_KINETIC_ENERGY) {
        pos += speed * dt;
    }

        if (decaying) decayTime += dt;
        decay();
        //Update the age of the node renderer
        renderer.increment_idle_time(dt);

    TRACE("Node " << label << " now in pos=(" << pos.x << ", " << pos.y <<")");

    //TRACE("Step computed for " << id << ". Speed is " << speed.x << ", " << speed.y << " (energy: " << kinetic_energy << ").");

}

void Node::render(rendering_mode mode, MemoryView& env, bool debug){

#ifndef TEXT_ONLY
        if (mode == GRAPHVIZ) {
            env.graphvizGraph << safeid;
        }
        renderer.activation = activity;
        renderer.draw(pos, mode, env, distance_to_selected);

        if (debug) {
            vec4f col(1.0, 0.2, 0.2, 0.7);
            MemoryView::drawVector(hookeForce , pos, col);

            col = vec4f(0.2, 1.0, 0.2, 0.7);
            MemoryView::drawVector(coulombForce , pos, col);
        }

#endif

}

void Node::decay() {

    if(decaying) {
        float decayRatio = 1.0 - decayTime / (DECAY_TIME * 100.0 / decaySpeed);

        if (decayRatio < 0.0) {
            // End of decay period
            decayRatio = 0.0;
            decaying = false;
            decayTime = 0.0;
            decaySpeed = 1.0;
        }

        renderer.decayRatio = decayRatio;

        charge = base_charge + ((charge - base_charge) * decayRatio);
    }
}

void Node::setSelected(bool select) {

    if ((select && _selected)||
    (!select && !_selected)) return;

    _selected = select;
    renderer.setSelected(select);

}

void Node::hovered(bool hovered) {

    renderer.setMouseOver(hovered);
    _hovered = hovered;
}

std::ostream& operator<<(std::ostream& os, const Node& n)
{
    os << n.label;
    return os;
}

max_stars_repo_name: severin-lemaignan/memory-view

max_issues_repo_name: severin-lemaignan/memory-view

max_forks_repo_name: severin-lemaignan/memory-view


text:
#pragma once
#include <iostream>
#include <random>
#include <cmath>
#include <Eigen/Dense>
#include <Eigen/Geometry>

#define EPSILON 1e-6f
#define DELTA 1e-4f
#define PI 3.14159265358979323846f
#define PI_INV 0.31830988618f

namespace mathext {
    std::default_random_engine random_generator;

    std::vector<float> unif(float a, float b, int N = 1)
    {
        std::vector<float> res;
        std::uniform_real_distribution<float> dis(a, b);

        for (int i = 0; i < N; i++) {
            res.push_back(dis(random_generator));
        }
        return res;
    }

    Eigen::Vector2f disk(float r)
    {
        std::vector<float> u = unif(0.0f, 1.0f, 2);

        return Eigen::Vector2f(r * sqrt(u[0]), 2 * PI * u[1]);
    }

    Eigen::Matrix3f rot_from_two_vectors(Eigen::Vector3f src, Eigen::Vector3f des)
    {
        return Eigen::Quaternionf::FromTwoVectors(src, des).toRotationMatrix();
    }

    Eigen::Matrix3f rot_align_normal(Eigen::Vector3f n)
    {
        return rot_from_two_vectors(Eigen::Vector3f(0.0f, 0.0f, 1.0f), n);
    }

    Eigen::Vector3f reflect(Eigen::Vector3f v1, Eigen::Vector3f n)
    {
        return 2 * n.dot(v1) * n - v1;
    }

    Eigen::Vector3f refract(Eigen::Vector3f v1, Eigen::Vector3f n, float ior = 1.0f)
    {
        float cos_theta_i = v1.dot(n);
        float eta = 1 / ior;
        if (cos_theta_i < 0) {
            eta = 1 / eta;
            n *= -1;
            cos_theta_i *= -1;
        }
        float c = sqrt(1 - eta * eta * (1 - cos_theta_i * cos_theta_i));
        return c < 0 ? Eigen::Vector3f(0, 0, 0) : (eta * (-v1) + (eta * cos_theta_i - c) * n);
    }

    float power_heuristic(int n_f, float p_f, int n_g, float p_g, float beta = 2)
    {
        float c_f = (float)n_f * p_f, c_g = (float)n_g * p_g;
        return pow(c_f, beta) / (pow(c_f, beta) + pow(c_g, beta));
    }
}


text:
#include <ios>
#include <iostream>

#include <eposx_hardware/utils.h>

#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/make_shared.hpp>
#include <boost/program_options/errors.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/value_semantic.hpp>
#include <boost/program_options/variables_map.hpp>

namespace eh = eposx_hardware;
namespace bpo = boost::program_options;

// execute a given function in a try-catch barriar
template < typename T >
std::vector< T > barriar(const boost::function< std::vector< T >() > &func) {
  try {
    return func();
  } catch (const eh::EposException &error) {
    std::cerr << error.what() << std::endl;
  }
  return std::vector< T >();
}

int main(int argc, char *argv[]) {
  bool list_rs232;
  unsigned short max_node_id;
  try {
    // define available options
    bpo::options_description options;
    bool show_help;
    options.add(
        boost::make_shared< bpo::option_description >("help", bpo::bool_switch(&show_help)));
    options.add(
        boost::make_shared< bpo::option_description >("rs232", bpo::bool_switch(&list_rs232)));
    options.add(boost::make_shared< bpo::option_description >(
        "max-node-id", bpo::value(&max_node_id)->default_value(8)));
    // parse the command line
    bpo::variables_map args;
    bpo::store(bpo::parse_command_line(argc, argv, options), args);
    bpo::notify(args);
    // show help if requested
    if (show_help) {
      std::cout << "Available options:\n" << options << std::endl;
      return 0;
    }
  } catch (const bpo::error &error) {
    std::cerr << error.what() << std::endl;
    return 1;
  }

  std::cout << "Listing Nodes:" << std::endl;

  const std::vector< std::string > device_names(
      barriar< std::string >(boost::bind(eh::getDeviceNameList)));
  BOOST_FOREACH (const std::string &device_name, device_names) {
    std::cout << device_name << std::endl;

    const std::vector< std::string > protocol_stack_names(
        barriar< std::string >(boost::bind(eh::getProtocolStackNameList, device_name)));
    BOOST_FOREACH (const std::string &protocol_stack_name, protocol_stack_names) {
      std::cout << "\t" << protocol_stack_name << std::endl;

      const std::vector< std::string > interface_names(barriar< std::string >(
          boost::bind(eh::getInterfaceNameList, device_name, protocol_stack_name)));
      BOOST_FOREACH (const std::string &interface_name, interface_names) {
        std::cout << "\t\t" << interface_name << std::endl;
        if (!list_rs232 && interface_name == "RS232") {
          std::cout << "\t\t\tSkipping RS232" << std::endl;
          continue;
        }

        const std::vector< std::string > port_names(barriar< std::string >(
            boost::bind(eh::getPortNameList, device_name, protocol_stack_name, interface_name)));
        BOOST_FOREACH (const std::string &port_name, port_names) {
          std::cout << "\t\t\t" << port_name << std::endl;

          const std::vector< unsigned int > baudrates(barriar< unsigned int >(boost::bind(
              eh::getBaudrateList, device_name, protocol_stack_name, interface_name, port_name)));
          std::cout << "\t\t\t\tBaudrates:" << std::endl;
          BOOST_FOREACH (unsigned int baudrate, baudrates) {
            std::cout << "\t\t\t\t\t" << std::dec << baudrate << std::endl;
          }

          const std::vector< eh::NodeInfo > nodes(barriar< eh::NodeInfo >(boost::bind(
              eh::enumerateNodes,
              eh::DeviceInfo(device_name, protocol_stack_name, interface_name, port_name),
              0 /* no specific node id*/, max_node_id)));
          std::cout << "\t\t\t\tNodes (up to Node Id " << max_node_id << "):" << std::endl;
          BOOST_FOREACH (const eh::NodeInfo &node, nodes) {
            std::cout << "\t\t\t\t\tNode Id: " << std::dec << node.node_id << std::endl;
            std::cout << "\t\t\t\t\t\tSerial Number: 0x" << std::hex << node.serial_number
                      << std::endl;
            std::cout << "\t\t\t\t\t\tHardware Version: 0x" << std::hex << node.hardware_version
                      << std::endl;
            std::cout << "\t\t\t\t\t\tSoftware Version: 0x" << std::hex << node.software_version
                      << std::endl;
            std::cout << "\t\t\t\t\t\tApplication Number: 0x" << std::hex << node.application_number
                      << std::endl;
            std::cout << "\t\t\t\t\t\tApplication Version: 0x" << std::hex
                      << node.application_version << std::endl;
          }
        }
      }
    }
  }

  return 0;
}


text:
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <arpa/inet.h>

#include <boost/crc.hpp>

void
usage()
{
	fprintf(stderr, "Usage: crctool [-w] [-S start_offset] filename\n");
	exit(1);
}

int
main(int argc, char * const*argv)
{
	struct stat fstat;
	FILE *foo;
	void *data;
	uint32_t result;
	int ret;
	bool write = false;
	int start = 0;

	do {
		ret = getopt(argc, argv, "wS:");
		switch (ret) {
		case '?':
			usage();
			break;
		case 'w':
			write = true;
			break;
		case 'S':
			start = atoi(optarg);
			break;
		}
	} while (ret != -1);

	if (optind != argc - 1)
		usage();

	ret = stat(argv[optind], &fstat);
	if (ret < 0) {
		fprintf(stderr, "Could not stat %s", argv[optind]);
		perror("");
		exit(1);
	}

	foo = fopen(argv[optind], "r+b");
	if (foo == NULL) {
		perror("Could not open input file");
		exit(1);
	}

	// Skip past first 'start' bytes.
	fseek(foo, start, SEEK_SET);
	int size = fstat.st_size - start;

	data = malloc(size);
	if (data == NULL) {
		fprintf(stderr, "OOM\n");
		exit(1);
	}

	if (fread(data, size, 1, foo) != 1) {
		fprintf(stderr, "Could not read whole input file\n");
		exit(1);
	}

	// Flip all 32 bit words. Really.
	{
		uint32_t *ptr = (uint32_t*)data;
		unsigned long count = size / 4;
		assert((size % 4) == 0);

		for (unsigned long i = 0; i < count; i++)
			// XXX: baked in assumption that this'll actually swap
			// bytes around.
			ptr[i] = htonl(ptr[i]);
	}

	boost::crc_basic<32> crc32(0x04C11DB7, 0xFFFFFFFF, 0, false, false);
	crc32.process_bytes(data, size);
	result = crc32.checksum();
	free(data);

	if (write) {
		fseek(foo, start+8, SEEK_SET);
		fwrite(&result, sizeof(result), 1, foo);
	} else {
		printf("%X\n", result);
	}

	fclose(foo);
	return 0;
}

max_stars_repo_name: srobo/dfu-bootloader

max_issues_repo_name: srobo/dfu-bootloader

max_forks_repo_name: srobo/dfu-bootloader