text:
#ifndef UUID_1846E497_4817_47F8_8588_147E6B9962C9
#define UUID_1846E497_4817_47F8_8588_147E6B9962C9
#pragma once

#include <boost/config.hpp>

#ifndef __has_builtin
#  define __has_builtin(x) 0
#endif

#if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
#  define NEPTOOLS_BUILTIN_UNREACHABLE() __builtin_unreachable()
#else
#  define NEPTOOLS_BUILTIN_UNREACHABLE() abort()
#endif

#if __has_builtin(__builtin_assume)
#  define NEPTOOLS_ASSUME(expr) __builtin_assume(!!(expr))
#else
#  define NEPTOOLS_ASSUME(expr) ((void) 0)
#endif

#ifdef NDEBUG
#  define NEPTOOLS_ASSERT(expr) NEPTOOLS_ASSUME(expr)
#  define NEPTOOLS_ASSERT_MSG(expr, msg) NEPTOOLS_ASSUME(expr)
#  define NEPTOOLS_UNREACHABLE(x) NEPTOOLS_BUILTIN_UNREACHABLE()

#else

#  include "file.hpp"

#  define NEPTOOLS_ASSERT(expr) \
    (BOOST_LIKELY(!!(expr)) ? ((void)0) : NEPTOOLS_ASSERT_FAILED(#expr, nullptr))

#  define NEPTOOLS_ASSERT_MSG(expr, msg) \
    (BOOST_LIKELY(!!(expr)) ? ((void)0) : NEPTOOLS_ASSERT_FAILED(#expr, msg))

#  define NEPTOOLS_ASSERT_FAILED(expr, msg)                      \
    ::Neptools::AssertFailed(expr, msg, NEPTOOLS_FILE, __LINE__, \
                             NEPTOOLS_FUNCTION)

#  define NEPTOOLS_UNREACHABLE(x)                   \
    do                                              \
    {                                               \
        NEPTOOLS_ASSERT_FAILED("unreachable", x);   \
        /* click on ignore -> you're toasted */     \
        NEPTOOLS_BUILTIN_UNREACHABLE();             \
    } while (0)
#endif

namespace Neptools
{
#ifndef WINDOWS
BOOST_NORETURN
#endif
void AssertFailed(
    const char* expr, const char* msg, const char* file, unsigned line,
    const char* fun);

}

#endif

ext: hpp

max_stars_repo_name: clienthax/neptools

max_issues_repo_name: clienthax/neptools

max_forks_repo_name: clienthax/neptools


text:
#ifndef SAGA_IMPL_PACKAGES_DATA_NAMESPACE_NAMESPACEDIR_HPP
#define SAGA_IMPL_PACKAGES_DATA_NAMESPACE_NAMESPACEDIR_HPP

#if defined(__WAVE__) && defined(SAGA_CREATE_PREPROCESSED_FILES)
#pragma wave option(preserve: 2, line: 0, output: "preprocessed/namespace_dir.hpp")
#endif
//  Copyright (c) 2005-2007 Andre Merzky (andre@merzky.net)
//  Copyright (c) 2005-2009 Hartmut Kaiser
//  Copyright (c) 2005 Michel Zandstra [michelzandstra@gmail.com]
//
//  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)

#if defined(__WAVE__) && defined(SAGA_CREATE_PREPROCESSED_FILES)
#pragma wave option(output: null)
#endif
#include <boost/shared_ptr.hpp>

#include <string>

#include <saga/saga/session.hpp>
#include <saga/impl/call.hpp>
#include <saga/impl/engine/proxy.hpp>

#include <saga/impl/packages/namespace/namespace_dir_cpi.hpp>
#include <saga/impl/packages/namespace/namespace_entry.hpp>

#ifdef SAGA_DEBUG
#include <saga/impl/packages/namespace/preprocessed/namespace_dir.hpp>
#else

#if defined(__WAVE__) && defined(SAGA_CREATE_PREPROCESSED_FILES)
#pragma wave option(output: "preprocessed/namespace_dir.hpp")
#endif
///////////////////////////////////////////////////////////////////////////////
namespace saga
{
  namespace impl
  {
    /**
     * This class acts as a proxy class, hiding all the nasty Saga stuff
     * (like creating and using adaptors) for the user. Users just call
     * the functions of this class like to would on every local object,
     * and don't have to worry about adaptors. It extends
     * saga::name_space::directory_cpi.
     */
    class SAGA_NAMESPACE_PACKAGE_EXPORT namespace_dir
        : public saga::impl::namespace_entry   // v1_0::namespace_dir_cpi
    {
      typedef v1_0::namespace_dir_cpi namespace_dir_cpi;
      typedef v1_0::preference_type preference_type;

      bool need_to_free_instance_data;

      // initialize newly attached CPI instance
      void init();

     protected:
      namespace_dir (saga::session const & s,
          saga::object::type t = saga::object::NSDirectory);
      explicit namespace_dir (saga::object::type t);

     public:
      /**
       * Constructor of namespace_dir, sets the location of the namespace_dir, and gets
       * an instance of the Saga engine
       *
       * @param loc the full path and name of the namespace_dir
       * @param s   the session handle
       */
      namespace_dir (saga::session const& s, saga::url loc, int mode,
          saga::object::type t = saga::object::NSDirectory);

      /*! destructor of namespace_dir, destroys namespace_dir and the adaptor it is
       *  bound to */
      ~namespace_dir (void);

      // factories
      void create_impl_sync(name_space::directory& retval);
      static saga::task create_impl_async(saga::session const& s, saga::url url, int mode);

      // navigation/query methods
      SAGA_CALL_IMPL_DECL_1(change_dir, saga::url)
      SAGA_CALL_IMPL_DECL_2(list, std::string, int)
      SAGA_CALL_IMPL_DECL_2(find, std::string, int)

      SAGA_CALL_IMPL_DECL_1(read_link, saga::url)
      SAGA_CALL_IMPL_DECL_1(exists, saga::url)
      SAGA_CALL_IMPL_DECL_1(is_dir, saga::url)
      SAGA_CALL_IMPL_DECL_1(is_entry, saga::url)
      SAGA_CALL_IMPL_DECL_1(is_link, saga::url)

      // Deal with entries by entry number
      SAGA_CALL_IMPL_DECL_0(get_num_entries)
      SAGA_CALL_IMPL_DECL_1(get_entry, std::size_t)

      // entry management methods
      SAGA_CALL_IMPL_DECL_3(copy, saga::url, saga::url, int)
      SAGA_CALL_IMPL_DECL_3(link, saga::url, saga::url, int)
      SAGA_CALL_IMPL_DECL_3(move, saga::url, saga::url, int)
      SAGA_CALL_IMPL_DECL_2(remove, saga::url, int)
      SAGA_CALL_IMPL_DECL_2(make_dir, saga::url, int)

      // open methods
      SAGA_CALL_IMPL_DECL_2(open, saga::url, int)
      SAGA_CALL_IMPL_DECL_2(open_dir, saga::url, int)

      // entry management methods - wild card versions
      SAGA_CALL_IMPL_DECL_3(copy_wildcard, std::string, saga::url, int)
      SAGA_CALL_IMPL_DECL_3(link_wildcard, std::string, saga::url, int)
      SAGA_CALL_IMPL_DECL_3(move_wildcard, std::string, saga::url, int)
      SAGA_CALL_IMPL_DECL_2(remove_wildcard, std::string, int)

      // permissions with flags
      SAGA_CALL_IMPL_DECL_4(permissions_allow, saga::url, std::string, int, int)
      SAGA_CALL_IMPL_DECL_4(permissions_deny, saga::url, std::string, int, int)
      SAGA_CALL_IMPL_DECL_4(permissions_allow_wildcard, std::string, std::string, int, int)
      SAGA_CALL_IMPL_DECL_4(permissions_deny_wildcard, std::string, std::string, int, int)

      // Generate a exact deep copy of this object
      saga::object clone() const;
    };

  }  // namespace impl
} // namespace saga
///////////////////////////////////////////////////////////////////////////////

#if defined(__WAVE__) && defined(SAGA_CREATE_PREPROCESSED_FILES)
#pragma wave option(output: null)
#endif
#endif // !defined(SAGA_DEBUG)

#endif // SAGA_IMPL_PACKAGES_DATA_NAMESPACE_NAMESPACEDIR_HPP

max_stars_repo_name: saga-project/saga-cpp

max_issues_repo_name: saga-project/saga-cpp

max_forks_repo_name: saga-project/saga-cpp


text:
/**
 * Orthanc - A Lightweight, RESTful DICOM Store
 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
 * Department, University Hospital of Liege, Belgium
 * Copyright (C) 2017-2020 Osimis S.A., Belgium
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 **/

/*=========================================================================

  This file is based on portions of the following project:

  Program: DCMTK 3.6.0
  Module:  http://dicom.offis.de/dcmtk.php.en

Copyright (C) 1994-2011, OFFIS e.V.
All rights reserved.

This software and supporting documentation were developed by

  OFFIS e.V.
  R&D Division Health
  Escherweg 2
  26121 Oldenburg, Germany

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

- Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

- Neither the name of OFFIS nor the names of its contributors may be
  used to endorse or promote products derived from this software
  without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/

#include "../../PrecompiledHeaders.h"
#include "MoveScp.h"

#include <memory>

#include "../../DicomParsing/FromDcmtkBridge.h"
#include "../../DicomParsing/ToDcmtkBridge.h"
#include "../../Logging.h"
#include "../../OrthancException.h"

#include <boost/lexical_cast.hpp>

/**
 * Macro specifying whether to apply the patch suggested in issue 66:
 * "Orthanc responses C-MOVE with zero Move Originator Message ID"
 * https://bitbucket.org/sjodogne/orthanc/issues/66/
 **/

#define APPLY_FIX_ISSUE_66   1

namespace Orthanc
{
  namespace
  {
    struct MoveScpData
    {
      std::string target_;
      IMoveRequestHandler* handler_;
      DcmDataset* lastRequest_;
      unsigned int subOperationCount_;
      unsigned int failureCount_;
      unsigned int warningCount_;
      std::unique_ptr<IMoveRequestIterator> iterator_;
      const std::string* remoteIp_;
      const std::string* remoteAet_;
      const std::string* calledAet_;
    };

#if APPLY_FIX_ISSUE_66 != 1
    static uint16_t GetMessageId(const DicomMap& message)
    {
      /**
       * Retrieve the Message ID (0000,0110) for this C-MOVE request, if
       * any. If present, this Message ID will be stored in the Move
       * Originator Message ID (0000,1031) field of the C-MOVE response.
       * http://dicom.nema.org/dicom/2013/output/chtml/part07/chapter_E.html
       **/

      const DicomValue* value = message.TestAndGetValue(DICOM_TAG_MESSAGE_ID);

      if (value != NULL &&
          !value->IsNull() &&
          !value->IsBinary())
      {
        try
        {
          int tmp = boost::lexical_cast<int>(value->GetContent());
          if (tmp >= 0 && tmp <= 0xffff)
          {
            return static_cast<uint16_t>(tmp);
          }
        }
        catch (boost::bad_lexical_cast&)
        {
          LOG(WARNING) << "Cannot convert the Message ID (\"" << value->GetContent()
                       << "\") of an incoming C-MOVE request to an integer, assuming zero";
        }
      }

      return 0;
    }
#endif

    void MoveScpCallback(
      /* in */
      void *callbackData,
      OFBool cancelled,
      T_DIMSE_C_MoveRQ *request,
      DcmDataset *requestIdentifiers,
      int responseCount,
      /* out */
      T_DIMSE_C_MoveRSP *response,
      DcmDataset **responseIdentifiers,
      DcmDataset **statusDetail)
    {
      bzero(response, sizeof(T_DIMSE_C_MoveRSP));
      *statusDetail = NULL;
      *responseIdentifiers = NULL;

      MoveScpData& data = *reinterpret_cast<MoveScpData*>(callbackData);
      if (data.lastRequest_ == NULL)
      {
        DicomMap input;
        std::set<DicomTag> ignoreTagLength;
        FromDcmtkBridge::ExtractDicomSummary(input, *requestIdentifiers, 0 /* don't truncate tags */, ignoreTagLength);

        try
        {
#if APPLY_FIX_ISSUE_66 == 1
          uint16_t messageId = request->MessageID;
#else
          // The line below was the implementation for Orthanc <= 1.3.2
          uint16_t messageId = GetMessageId(input);
#endif

          data.iterator_.reset(data.handler_->Handle(data.target_, input, *data.remoteIp_, *data.remoteAet_,
                                                     *data.calledAet_, messageId));

          if (data.iterator_.get() == NULL)
          {
            // Internal error!
            response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess;
            return;
          }

          data.subOperationCount_ = data.iterator_->GetSubOperationCount();
          data.failureCount_ = 0;
          data.warningCount_ = 0;
        }
        catch (OrthancException& e)
        {
          // Internal error!
          LOG(ERROR) << "IMoveRequestHandler Failed: " << e.What();
          response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess;
          return;
        }

        data.lastRequest_ = requestIdentifiers;
      }
      else if (data.lastRequest_ != requestIdentifiers)
      {
        // Internal error!
        response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess;
        return;
      }

      if (data.subOperationCount_ == 0)
      {
        response->DimseStatus = STATUS_Success;
      }
      else
      {
        IMoveRequestIterator::Status status;

        try
        {
          status = data.iterator_->DoNext();
        }
        catch (OrthancException& e)
        {
          // Internal error!
          LOG(ERROR) << "IMoveRequestHandler Failed: " << e.What();
          response->DimseStatus = STATUS_MOVE_Failed_UnableToProcess;
          return;
        }

        if (status == IMoveRequestIterator::Status_Failure)
        {
          data.failureCount_++;
        }
        else if (status == IMoveRequestIterator::Status_Warning)
        {
          data.warningCount_++;
        }

        if (responseCount < static_cast<int>(data.subOperationCount_))
        {
          response->DimseStatus = STATUS_Pending;
        }
        else
        {
          response->DimseStatus = STATUS_Success;
        }
      }

      response->NumberOfRemainingSubOperations = data.subOperationCount_ - responseCount;
      response->NumberOfCompletedSubOperations = responseCount;
      response->NumberOfFailedSubOperations = data.failureCount_;
      response->NumberOfWarningSubOperations = data.warningCount_;
    }
  }

  OFCondition Internals::moveScp(T_ASC_Association * assoc,
                                 T_DIMSE_Message * msg,
                                 T_ASC_PresentationContextID presID,
                                 IMoveRequestHandler& handler,
                                 const std::string& remoteIp,
                                 const std::string& remoteAet,
                                 const std::string& calledAet,
                                 int timeout)
  {
    MoveScpData data;
    data.target_ = std::string(msg->msg.CMoveRQ.MoveDestination);
    data.lastRequest_ = NULL;
    data.handler_ = &handler;
    data.remoteIp_ = &remoteIp;
    data.remoteAet_ = &remoteAet;
    data.calledAet_ = &calledAet;

    OFCondition cond = DIMSE_moveProvider(assoc, presID, &msg->msg.CMoveRQ,
                                          MoveScpCallback, &data,
                                          /*opt_blockMode*/ (timeout ? DIMSE_NONBLOCKING : DIMSE_BLOCKING),
                                          /*opt_dimse_timeout*/ timeout);

    // if some error occured, dump corresponding information and remove the outfile if necessary
    if (cond.bad())
    {
      OFString temp_str;
      LOG(ERROR) << "Move SCP Failed: " << cond.text();
    }

    return cond;
  }
}

ext: cpp


text:
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "net/dns.hpp"

#include "boost-test.hpp"
#include "network-configuration-detector.hpp"

#include <boost/asio/io_service.hpp>

namespace ndn {
namespace dns {
namespace tests {

using boost::asio::ip::address_v4;
using boost::asio::ip::address_v6;

class DnsFixture
{
public:
  DnsFixture()
    : m_nFailures(0)
    , m_nSuccesses(0)
  {
  }

  void
  onSuccess(const IpAddress& resolvedAddress,
            const IpAddress& expectedAddress,
            bool isValid,
            bool shouldCheckAddress = false)
  {
    ++m_nSuccesses;

    if (!isValid) {
      BOOST_FAIL("Resolved to " + resolvedAddress.to_string() + ", but should have failed");
    }

    BOOST_CHECK_EQUAL(resolvedAddress.is_v4(), expectedAddress.is_v4());

    // checking address is not deterministic and should be enabled only
    // if only one IP address will be returned by resolution
    if (shouldCheckAddress) {
      BOOST_CHECK_EQUAL(resolvedAddress, expectedAddress);
    }
  }

  void
  onFailure(bool isValid)
  {
    ++m_nFailures;

    if (!isValid) {
      BOOST_FAIL("Resolution should not have failed");
    }

    BOOST_CHECK_MESSAGE(true, "Resolution failed as expected");
  }

protected:
  uint32_t m_nFailures;
  uint32_t m_nSuccesses;
  boost::asio::io_service m_ioService;
};

BOOST_AUTO_TEST_SUITE(Net)
BOOST_FIXTURE_TEST_SUITE(TestDns, DnsFixture)

BOOST_AUTO_TEST_CASE(Asynchronous)
{
  SKIP_IF_IP_UNAVAILABLE();

  asyncResolve("nothost.nothost.nothost.arpa",
               bind(&DnsFixture::onSuccess, this, _1, IpAddress(address_v4()), false, false),
               bind(&DnsFixture::onFailure, this, true),
               m_ioService); // should fail

  m_ioService.run();
  BOOST_CHECK_EQUAL(m_nFailures, 1);
  BOOST_CHECK_EQUAL(m_nSuccesses, 0);
}

BOOST_AUTO_TEST_CASE(AsynchronousV4)
{
  SKIP_IF_IPV4_UNAVAILABLE();

  asyncResolve("192.0.2.1",
               bind(&DnsFixture::onSuccess, this, _1,
                    IpAddress(address_v4::from_string("192.0.2.1")), true, true),
               bind(&DnsFixture::onFailure, this, false),
               m_ioService);

  m_ioService.run();
  BOOST_CHECK_EQUAL(m_nFailures, 0);
  BOOST_CHECK_EQUAL(m_nSuccesses, 1);
}

BOOST_AUTO_TEST_CASE(AsynchronousV6)
{
  SKIP_IF_IPV6_UNAVAILABLE();

  asyncResolve("ipv6.google.com", // only IPv6 address should be available
               bind(&DnsFixture::onSuccess, this, _1, IpAddress(address_v6()), true, false),
               bind(&DnsFixture::onFailure, this, false),
               m_ioService);

  asyncResolve("2001:db8:3f9:0:3025:ccc5:eeeb:86d3",
               bind(&DnsFixture::onSuccess, this, _1,
                    IpAddress(address_v6::from_string("2001:db8:3f9:0:3025:ccc5:eeeb:86d3")),
                    true, true),
               bind(&DnsFixture::onFailure, this, false),
               m_ioService);

  m_ioService.run();
  BOOST_CHECK_EQUAL(m_nFailures, 0);
  BOOST_CHECK_EQUAL(m_nSuccesses, 2);
}

BOOST_AUTO_TEST_CASE(AsynchronousV4AndV6)
{
  SKIP_IF_IPV4_UNAVAILABLE();
  SKIP_IF_IPV6_UNAVAILABLE();

  asyncResolve("www.named-data.net",
               bind(&DnsFixture::onSuccess, this, _1, IpAddress(address_v4()), true, false),
               bind(&DnsFixture::onFailure, this, false),
               m_ioService, Ipv4Only());

  asyncResolve("a.root-servers.net",
               bind(&DnsFixture::onSuccess, this, _1, IpAddress(address_v4()), true, false),
               bind(&DnsFixture::onFailure, this, false),
               m_ioService, Ipv4Only()); // request IPv4 address

  asyncResolve("a.root-servers.net",
               bind(&DnsFixture::onSuccess, this, _1, IpAddress(address_v6()), true, false),
               bind(&DnsFixture::onFailure, this, false),
               m_ioService, Ipv6Only()); // request IPv6 address

  asyncResolve("ipv6.google.com", // only IPv6 address should be available
               bind(&DnsFixture::onSuccess, this, _1, IpAddress(address_v6()), true, false),
               bind(&DnsFixture::onFailure, this, false),
               m_ioService, Ipv6Only());

  asyncResolve("ipv6.google.com", // only IPv6 address should be available
               bind(&DnsFixture::onSuccess, this, _1, IpAddress(address_v6()), false, false),
               bind(&DnsFixture::onFailure, this, true),
               m_ioService, Ipv4Only()); // should fail

  m_ioService.run();
  BOOST_CHECK_EQUAL(m_nFailures, 1);
  BOOST_CHECK_EQUAL(m_nSuccesses, 4);
}

BOOST_AUTO_TEST_CASE(Synchronous)
{
  SKIP_IF_IP_UNAVAILABLE();

  IpAddress address = syncResolve("www.named-data.net", m_ioService);
  BOOST_CHECK(address.is_v4() || address.is_v6());
}

BOOST_AUTO_TEST_SUITE_END() // TestDns
BOOST_AUTO_TEST_SUITE_END() // Net

} // namespace tests
} // namespace dns
} // namespace ndn


text:
/*
 * Copyright (c) 2018 IOTA Stiftung
 * https://github.com/iotaledger/hub
 *
 * Refer to the LICENSE file for licensing information
 */

#include "hub/service/attachment_service.h"

#include <algorithm>
#include <chrono>
#include <iterator>
#include <unordered_map>
#include <vector>

#include <gflags/gflags.h>
#include <glog/logging.h>
#include <boost/functional/hash.hpp>
#include "common/model/bundle.h"
#include "common/model/transaction.h"

#include "common/helpers/digest.h"
#include "hub/db/helper.h"
#include "hub/iota/pow.h"

namespace {
DEFINE_uint32(
    max_promotion_age, 30,
    "Maximum age [minutes] for a sweep's tail which allows promotion, (i.e - a "
    "tail that's older than that will not be promoted, rather sweep "
    "will be reattached)");
}  // namespace

namespace hub {
namespace service {

bool AttachmentService::checkSweepTailsForConfirmation(
    db::Connection& connection, const db::Sweep& sweep,
    const std::vector<std::string>& tails) {
  VLOG(3) << __FUNCTION__;
  auto confirmedTails = _api->filterConfirmedTails(tails, {});

  LOG(INFO) << "Sweep: " << sweep.id << " (" << sweep.bundleHash
            << ") has: " << confirmedTails.size() << " confirmed tails.";

  if (confirmedTails.empty()) {
    return false;
  }

  auto tailIt = confirmedTails.cbegin();
  LOG(INFO) << "Marking tail as confirmed: " << *tailIt;
  connection.markTailAsConfirmed(*tailIt);
  if (confirmedTails.size() > 1) {
    LOG(ERROR) << "More than one confirmed tail for sweep: " << sweep.id
               << " bundle hash: " << sweep.bundleHash;
    LOG(INFO) << "Ignored tails:";
    while (++tailIt != confirmedTails.cend()) {
      LOG(INFO) << *tailIt;
    }
  }

  return true;
}

bool AttachmentService::checkForUserReattachment(
    db::Connection& connection, const db::Sweep& sweep,
    const std::vector<std::string>& knownTails) {
  VLOG(3) << __FUNCTION__;
  auto bundleTransactionHashes = _api->findTransactions(
      {}, std::vector<std::string>{sweep.bundleHash}, {});
  auto bundleTransactions =
      _api->getTransactions(bundleTransactionHashes, false);

  // Remove non-tails or tails that we know of
  bundleTransactions.erase(
      std::remove_if(bundleTransactions.begin(), bundleTransactions.end(),
                     [&knownTails](const auto& tx) {
                       return
                           // Not a tail
                           tx.currentIndex != 0 ||
                           // Already know about this one
                           std::find(knownTails.begin(), knownTails.end(),
                                     tx.hash) != knownTails.end();
                     }),
      bundleTransactions.end());

  if (bundleTransactions.size() != 0) {
    // Third-party (i.e. user erattachments!)
    std::vector<std::string> userTails;

    for (const auto& ref : bundleTransactions) {
      userTails.push_back(ref.hash);
    }

    auto confirmedTails = _api->filterConfirmedTails(userTails, {});
    if (confirmedTails.size() == 1) {
      const auto& tail = *confirmedTails.cbegin();
      LOG(INFO) << "Inserting confirmed user-attached tail: " << tail;
      connection.createTail(sweep.id, tail);

      LOG(INFO) << "Marking tail as confirmed: " << tail;
      connection.markTailAsConfirmed(tail);
      return true;
    }

    if (confirmedTails.size() > 1) {
      // This should be impossible since bundle spends all funds
      // in any input address, meaning that it won't be validated after one
      // bundle has been confirmed
      LOG(FATAL) << "Bundle hash: " << sweep.bundleHash
                 << " has more than one confirmed tail";
    }

    // This also makes sure that we only add bundles that IRI has seen
    // fully.
    auto consistentTails = _api->filterConsistentTails(userTails);

    if (consistentTails.size() != 0) {
      for (const auto& tail : consistentTails) {
        LOG(INFO) << "Inserting Unconfirmed user-attached tail: " << tail;
        connection.createTail(sweep.id, tail);
      }
    }
  }
  return false;
}

void AttachmentService::reattachSweep(db::Connection& dbConnection,
                                      const iota::POWProvider& powProvider,
                                      const db::Sweep& sweep) {
  VLOG(3) << __FUNCTION__;
  auto attachedTrytes = powProvider.performPOW(sweep.trytes);
  if (attachedTrytes.empty()) {
    LOG(ERROR) << "Failed in POW for sweep with bundle's hash: "
               << sweep.bundleHash;
    return;
  }
  // Get tail hash of first tx:
  auto tailHash = iota_digest(attachedTrytes[0].c_str());
  LOG(INFO) << "Reattached sweep " << sweep.id << " as: " << tailHash;

  if (!_api->storeTransactions(attachedTrytes)) {
    std::free(tailHash);
    LOG(ERROR)
        << "Failed in \"storeTransactions\" for sweep with bundle's hash: "
        << sweep.bundleHash;
    return;
  }
  if (!_api->broadcastTransactions(attachedTrytes)) {
    std::free(tailHash);
    LOG(ERROR)
        << "Failed in \"broadcastTransactions\" for sweep with bundle's hash: "
        << sweep.bundleHash;
    return;
  }

  dbConnection.createTail(sweep.id, tailHash);

  std::free(tailHash);
}

void AttachmentService::promoteSweep(db::Connection& connection,
                                     const iota::POWProvider& powProvider,
                                     const db::Sweep& sweep,
                                     const common::crypto::Hash& tailHash) {
  VLOG(3) << __FUNCTION__;
  auto maybeToApprove = _api->getTransactionsToApprove(0, {tailHash.str()});
  if (!maybeToApprove.has_value()) {
    LOG(ERROR) << "Failed to get  transactions to approve";
    return;
  }
  auto toApprove = maybeToApprove.value();
  auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(
                       std::chrono::system_clock::now().time_since_epoch())
                       .count();

  Kerl kerl;
  kerl_init(&kerl);

  bundle_transactions_t* bundle = NULL;
  iota_transaction_t txE;
  bundle_transactions_new(&bundle);

  transaction_reset(&txE);

  flex_trit_t addressFlexTrits[FLEX_TRIT_SIZE_243];
  flex_trits_from_trytes(addressFlexTrits, NUM_TRITS_ADDRESS,
                       (tryte_t*)      "SOME9RANDOM9HUB9BEING9REATTACHED9999999999999999999999999999999999999999"
                                       "999999999",
                       NUM_TRYTES_ADDRESS, NUM_TRYTES_ADDRESS);

  transaction_set_address(&txE, addressFlexTrits);
  transaction_set_value(&txE, 0uLL);
  transaction_set_timestamp(&txE, timestamp);

  txE.loaded_columns_mask.attachment |= MASK_ATTACHMENT_TAG;
  txE.loaded_columns_mask.essence |= MASK_ESSENCE_OBSOLETE_TAG;

  bundle_transactions_add(bundle, &txE);
  bundle_reset_indexes(bundle);
  bundle_finalize(bundle, &kerl);

  flex_trit_t txFlexTrits[FLEX_TRIT_SIZE_8019];
  char txTrytesStr[NUM_TRYTES_SERIALIZED_TRANSACTION + 1];
  transaction_serialize_on_flex_trits(&txE, txFlexTrits);
  flex_trits_to_trytes((tryte_t*)txTrytesStr, NUM_TRYTES_SERIALIZED_TRANSACTION,
                       txFlexTrits, NUM_TRITS_SERIALIZED_TRANSACTION,
                       NUM_TRITS_SERIALIZED_TRANSACTION);
  txTrytesStr[NUM_TRYTES_SERIALIZED_TRANSACTION] = 0;

  auto attachedTrytes = powProvider.doPOW(
      {txTrytesStr}, toApprove.trunkTransaction, toApprove.branchTransaction);

  _api->storeTransactions(attachedTrytes);
  _api->broadcastTransactions(attachedTrytes);

  auto promotionHash = iota_digest(attachedTrytes[0].c_str());
  LOG(INFO) << "Issued promotion for sweep " << sweep.id << ": "
            << promotionHash;
  std::free(promotionHash);
}

bool AttachmentService::doTick() {
  // We're splitting processing out to separate methods on purpose.
  // This means, that we can't really batch API requests across sweeps.
  // Shouldn't matter though as we simply assume that the IOTA node is only used
  // by Hub.
  VLOG(3) << __FUNCTION__;

  auto& connection = db::DBManager::get().connection();
  auto& powProvider = iota::POWManager::get().provider();

  auto tickStart = std::chrono::system_clock::now();

  // 1. Get Unconfirmed sweeps from database.
  auto unconfirmedSweeps = connection.getUnconfirmedSweeps(tickStart);
  LOG(INFO) << "Found " << unconfirmedSweeps.size() << " unconfirmed sweeps.";

  for (const auto& sweep : unconfirmedSweeps) {
    auto transaction = connection.transaction();

    if (!_api->getNodeInfo().has_value()) {
      return false;
    }

    auto milestone = _api->getNodeInfo().value().latestMilestone;

    try {
      // 2. Get (tails, timestamp) for these sweeps
      const auto initialSweepInfos = connection.getTailsForSweep(sweep.id);

      std::vector<std::string> initialSweepTailHashes;
      std::transform(std::begin(initialSweepInfos), std::end(initialSweepInfos),
                     std::back_inserter(initialSweepTailHashes),
                     [](const auto& sweepTail) { return sweepTail.hash; });

      // 3. Check if one of the tails is confirmed.
      // 4. If not, check if a user reattachment was confirmed
      if (checkSweepTailsForConfirmation(connection, sweep,
                                         initialSweepTailHashes) ||
          checkForUserReattachment(connection, sweep, initialSweepTailHashes)) {
        LOG(INFO) << "Sweep " << sweep.id << " is CONFIRMED.";
      } else {
        LOG(INFO) << "Sweep " << sweep.id << " is still unconfirmed.";

        // 5. If not, check if at least one of the tails per sweep is still
        //    promotable
        // Requerying list of tails because `checkForUserReattachment` might
        // have added some.
        const auto sweepTails = connection.getTailsForSweep(sweep.id);
        std::vector<std::string> sweepTailHashes;
        std::transform(std::begin(sweepTails), std::end(sweepTails),
                       std::back_inserter(sweepTailHashes),
                       [](const auto& sweepTail) { return sweepTail.hash; });
        auto consistentTails = _api->filterConsistentTails(sweepTailHashes);
        // 5.1. If yes, pick most recent and promote.
        if (consistentTails.size() > 0) {
          // Get newest tail.
          auto toPromote = std::find_if(
              sweepTails.begin(), sweepTails.end(),
              [&consistentTails](const auto& tail) {
                return consistentTails.find(tail.hash) !=
                           consistentTails.end() &&
                       std::chrono::duration_cast<std::chrono::minutes>(
                           std::chrono::system_clock::now() - tail.createdAt)
                               .count() < FLAGS_max_promotion_age;
              });

          if (toPromote != sweepTails.end()) {
            // Promotion can fail if getTransactionsToApprove fails!
            // In this case, we just catch and reattach.
            try {
              promoteSweep(connection, powProvider, sweep,
                           common::crypto::Hash((*toPromote).hash));
            } catch (const std::exception& ex) {
              LOG(INFO) << "Promotion failed. Reattaching.";
              reattachSweep(connection, powProvider, sweep);
            }
          } else {
            reattachSweep(connection, powProvider, sweep);
          }
        } else {
          // 6. If not, reattach and commit tail to DB.
          reattachSweep(connection, powProvider, sweep);
        }
      }

      transaction->commit();
    } catch (const std::exception& ex) {
      LOG(ERROR) << "Sweep " << sweep.id
                 << " failed to commit to DB: " << ex.what();

      try {
        transaction->rollback();
      } catch (const std::exception& ex) {
        LOG(ERROR) << "Sweep " << sweep.id << " rollback failed: " << ex.what();
      }
    }
  }

  return true;
}
}  // namespace service
}  // namespace hub

ext: cc

max_stars_repo_name: loveandpeople/hub

max_issues_repo_name: loveandpeople/hub

max_forks_repo_name: loveandpeople/hub


text:
#include "Day06-ChronalCoordinates.h"

#include "GridAreaAnalyzer.h"

#include <AdventOfCodeCommon/DisableLibraryWarningsMacros.h>

__BEGIN_LIBRARIES_DISABLE_WARNINGS
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
__END_LIBRARIES_DISABLE_WARNINGS

namespace AdventOfCode
{
namespace Year2018
{
namespace Day06
{

std::vector<Coordinates> parseCoordinates(const std::vector<std::string>& coordinatesLines)
{
    std::vector<Coordinates> allCoordinates;

    for (const auto& lines : coordinatesLines)
    {
        std::vector<std::string> tokens;
        boost::split(tokens, lines, boost::is_any_of(" ,"), boost::token_compress_on);

        unsigned x = boost::lexical_cast<unsigned>(tokens[0]);
        unsigned y = boost::lexical_cast<unsigned>(tokens[1]);

        allCoordinates.emplace_back(x, y);
    }

    return allCoordinates;
}

unsigned sizeOfLargestNonInfiniteArea(const std::vector<std::string>& coordinatesLines)
{
    std::vector<Coordinates> allCoordinates = parseCoordinates(coordinatesLines);

    GridAreaAnalyzer gridAnalyzer{std::move(allCoordinates)};

    return gridAnalyzer.getLargestNonInfiniteArea();
}

unsigned sizeOfAreaWithinGivenDistance(const std::vector<std::string>& coordinatesLines, unsigned distanceThreshold)
{
    std::vector<Coordinates> allCoordinates = parseCoordinates(coordinatesLines);

    GridAreaAnalyzer gridAnalyzer{std::move(allCoordinates)};

    return gridAnalyzer.getAreaWithinGivenDistance(distanceThreshold);
}

}
}
}

max_stars_repo_name: dbartok/advent-of-code-cpp

max_issues_repo_name: dbartok/advent-of-code-cpp

max_forks_repo_name: dbartok/advent-of-code-cpp


text:
// Boost.Units - A C++ library for zero-overhead dimensional analysis and
// unit/quantity manipulation and conversion
//
// Copyright (C) 2003-2008 Matthias Christian Schabel
// Copyright (C) 2008 Steven Watanabe
//
// 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_UNITS_CODATA_NEUTRON_CONSTANTS_HPP
#define BOOST_UNITS_CODATA_NEUTRON_CONSTANTS_HPP

#include <boost/units/static_constant.hpp>

#include <boost/units/systems/detail/constants.hpp>
#include <boost/units/systems/si/amount.hpp>
#include <boost/units/systems/si/area.hpp>
#include <boost/units/systems/si/electric_charge.hpp>
#include <boost/units/systems/si/energy.hpp>
#include <boost/units/systems/si/frequency.hpp>
#include <boost/units/systems/si/length.hpp>
#include <boost/units/systems/si/mass.hpp>
#include <boost/units/systems/si/magnetic_flux_density.hpp>
#include <boost/units/systems/si/time.hpp>
#include <boost/units/systems/si/wavenumber.hpp>

#include <boost/units/systems/si/codata/typedefs.hpp>

/// \file
/// CODATA recommended values of fundamental atomic and nuclear constants
/// CODATA 2006 values as of 2007/03/30

namespace boost {

namespace units {

namespace si {

namespace constants {

namespace codata {

/// CODATA recommended values of the fundamental physical constants: NIST SP 961

/// neutron mass
BOOST_UNITS_PHYSICAL_CONSTANT(m_n,quantity<mass>,1.674927211e-27*kilograms,8.4e-35*kilograms);
/// neutron-electron mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_n_over_m_e,quantity<dimensionless>,1838.6836605*dimensionless(),1.1e-6*dimensionless());
/// neutron-muon mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_n_over_m_mu,quantity<dimensionless>,8.89248409*dimensionless(),2.3e-7*dimensionless());
/// neutron-tau mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_n_over_m_tau,quantity<dimensionless>,0.528740*dimensionless(),8.6e-5*dimensionless());
/// neutron-proton mass ratio
BOOST_UNITS_PHYSICAL_CONSTANT(m_n_over_m_p,quantity<dimensionless>,1.00137841918*dimensionless(),4.6e-10*dimensionless());
/// neutron molar mass
BOOST_UNITS_PHYSICAL_CONSTANT(M_n,quantity<mass_over_amount>,1.00866491597e-3*kilograms/mole,4.3e-13*kilograms/mole);
/// neutron Compton wavelength
BOOST_UNITS_PHYSICAL_CONSTANT(lambda_C_n,quantity<length>,1.3195908951e-15*meters,2.0e-24*meters);
/// neutron magnetic moment
BOOST_UNITS_PHYSICAL_CONSTANT(mu_n,quantity<energy_over_magnetic_flux_density>,-0.96623641e-26*joules/tesla,2.3e-33*joules/tesla);
/// neutron g-factor
BOOST_UNITS_PHYSICAL_CONSTANT(g_n,quantity<dimensionless>,-3.82608545*dimensionless(),9.0e-7*dimensionless());
/// neutron-electron magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_n_over_mu_e,quantity<dimensionless>,1.04066882e-3*dimensionless(),2.5e-10*dimensionless());
/// neutron-proton magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_n_over_mu_p,quantity<dimensionless>,-0.68497934*dimensionless(),1.6e-7*dimensionless());
/// neutron-shielded proton magnetic moment ratio
BOOST_UNITS_PHYSICAL_CONSTANT(mu_n_over_mu_p_prime,quantity<dimensionless>,-0.68499694*dimensionless(),1.6e-7*dimensionless());
/// neutron gyromagnetic ratio
BOOST_UNITS_PHYSICAL_CONSTANT(gamma_n,quantity<frequency_over_magnetic_flux_density>,1.83247185e8/second/tesla,4.3e1/second/tesla);

} // namespace codata

} // namespace constants

} // namespace si

} // namespace units

} // namespace boost

#endif // BOOST_UNITS_CODATA_NEUTRON_CONSTANTS_HPP

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema


text: #include <boost/hana/mult.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
// Copyright  (C)  2007  Ruben Smits <ruben dot smits at mech dot kuleuven dot be>

// Version: 1.0
// Author: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// Maintainer: Ruben Smits <ruben dot smits at mech dot kuleuven dot be>
// URL: http://www.orocos.org/kdl

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

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

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef KDL_JACOBIAN_HPP
#define KDL_JACOBIAN_HPP

#include "frames.hpp"
#include <Eigen/Core>

namespace KDL
{
    // Equal is friend function, but default arguments for friends are forbidden (§8.3.6.4)
    class Jacobian;
    bool Equal( const Jacobian& a, const Jacobian& b, double eps = epsilon );
    void SetToZero( Jacobian& jac );

    class Jacobian
    {
    public:
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW
        Eigen::Matrix< double, 6, Eigen::Dynamic > data;
        Jacobian( );
        explicit Jacobian( unsigned int nr_of_columns );
        Jacobian( const Jacobian& arg );

        ///Allocates memory for new size (can break realtime behavior)
        void resize( unsigned int newNrOfColumns );

        ///Allocates memory if size of this and argument is different
        Jacobian& operator=( const Jacobian& arg );

        bool operator==( const Jacobian& arg ) const;
        bool operator!=( const Jacobian& arg ) const;

        friend bool Equal( const Jacobian& a, const Jacobian& b, double eps );

        ~Jacobian( );

        double operator( )( unsigned int i, unsigned int j ) const;
        double& operator( )( unsigned int i, unsigned int j );
        unsigned int rows( ) const;
        unsigned int columns( ) const;

        friend void SetToZero( Jacobian& jac );

        friend bool changeRefPoint( const Jacobian& src1, const Vector& base_AB, Jacobian& dest );
        friend bool changeBase( const Jacobian& src1, const Rotation& rot, Jacobian& dest );
        friend bool changeRefFrame( const Jacobian& src1, const Frame& frame, Jacobian& dest );

        Twist getColumn( unsigned int i ) const;
        void setColumn( unsigned int i, const Twist& t );

        void changeRefPoint( const Vector& base_AB );
        void changeBase( const Rotation& rot );
        void changeRefFrame( const Frame& frame );
    };

    bool changeRefPoint( const Jacobian& src1, const Vector& base_AB, Jacobian& dest );
    bool changeBase( const Jacobian& src1, const Rotation& rot, Jacobian& dest );
    bool changeRefFrame( const Jacobian& src1, const Frame& frame, Jacobian& dest );

}  // namespace KDL

#endif

max_stars_repo_name: rocos-sia/rocos-app


text:
/*
** EPITECH PROJECT, 2019
** ServerUdpMultiThreadWrapper.hpp
** File description:
**
*/

#pragma once
#include <memory>
#include <array>
#include <list>
#include <iostream>
#include <functional>
#include <boost/asio.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/array.hpp>
#include <boost/noncopyable.hpp>
#include <boost/format.hpp>

namespace uti::network {
    enum ProtocolType {BINARY, TEXT};
    template<class ProtocolDataPacket>
    class ServerTcpMultiThreadWrapper {
    public:

        // It is recommended to choose Binary as protocol type if you have control over the client
        explicit ServerTcpMultiThreadWrapper(ProtocolType protocolType)
                 : _online { false },
                  _inbound_header {},
                  _header_length { 8 },
                  _inbound_data {},
                  _protocolType { protocolType }
        {}

        void turnOn(const unsigned short int port,
                    std::function<void(int)> onAccept,
                    std::function<ProtocolDataPacket(const ProtocolDataPacket &, int)> onPacketReceived)
        {
            using boost::asio::ip::tcp;
            _sockets.push_back(tcp::socket(_io_context));

            _acceptor = std::make_unique<tcp::acceptor>(_io_context, tcp::endpoint(tcp::v4(), port));
            _online = true;

            while (true) {
                _acceptor->accept(_sockets.back());
                onAccept(_sockets.back().native_handle());
                const ProtocolDataPacket clientMessage = this->getIncomingClientMessage(_sockets.back());
                std::thread thread_obj(&uti::network::ServerTcpMultiThreadWrapper<ProtocolDataPacket>::_handleRequest,
                                       this,
                                       std::ref(_sockets),
                                       std::ref(_sockets.back()), // TODO: remove this extra param
                                       clientMessage,
                                       onPacketReceived
                                       );
                thread_obj.detach();
                if (!_online)
                    break;
                _sockets.push_back(tcp::socket(_io_context));
            }
        }

        ProtocolDataPacket getIncomingClientMessage(boost::asio::ip::tcp::socket &socket)
        {
            if (_protocolType == BINARY) {
                /* Receive the header */
                socket.receive(boost::asio::buffer(_inbound_header));

                std::istringstream is(std::string(_inbound_header, _header_length));
                std::size_t inbound_data_size = 0;

                if (!(is >> std::hex >> inbound_data_size)) {
                    std::cerr << "[CLientUdpMultiThread] Header is not valid : " << std::dec << inbound_data_size
                              << std::endl;
                    exit(31);
                }
                /* Conversion hex to dec */
                std::stringstream stream;
                size_t inbound_data_size_in_decimal = 0;

                stream << inbound_data_size;
                stream >> std::hex >> inbound_data_size_in_decimal;

                _inbound_data.resize(inbound_data_size_in_decimal);

                socket.receive(boost::asio::buffer(_inbound_data));

                ProtocolDataPacket t;
                try {
                    std::string archive_data(&_inbound_data[0], _inbound_data.size());
                    std::istringstream archive_stream(archive_data);
                    boost::archive::text_iarchive archive(archive_stream);
                    archive >> t;
                }
                catch (const std::exception &e) {
                    std::cerr << "[CLientUdpMultiThread] Unable to decode data.\n" << e.what() << std::endl;
                    exit(34);
                }
                return t;
            }
            else // _protocolType == TEXT
            {
                boost::array<char, 8089> incomingData {}; // TODO fix: what if they send more than 8089 char at once?
                socket.receive(boost::asio::buffer(incomingData));
                std::string incomingDataCast(incomingData.begin(), incomingData.end());
                return static_cast<ProtocolDataPacket>(incomingDataCast);
            }
        }

    private:
        void _handleRequest([[maybe_unused]] std::list<boost::asio::ip::tcp::socket> &sockets,
                            boost::asio::ip::tcp::socket &socket,
                            const ProtocolDataPacket data,
                            std::function<ProtocolDataPacket(const ProtocolDataPacket &, int)> onPacketReceived)
        {
            const ProtocolDataPacket serverReplyToClient = onPacketReceived(data, socket.native_handle());
            if (serverReplyToClient.size()) // Works for std::string
                _sendMessage(socket, serverReplyToClient);
            socket.close();
            // TODO remove the socket from the list of sockets after closing it.
        }

        void _sendMessage(boost::asio::ip::tcp::socket & socket, const ProtocolDataPacket & message)
        {
            if (_protocolType == BINARY) {
                // Serialization
                std::ostringstream archive_stream;
                boost::archive::text_oarchive archive(archive_stream);
                archive << message;
                std::string message_serialized = archive_stream.str();

                // Header creation
                std::ostringstream header_stream;
                header_stream << std::setw(static_cast<int>(_header_length)) \
 << std::hex << message_serialized.size();
                if (!header_stream || header_stream.str().size() != _header_length) {
                    std::cerr << "[CLientUdpMultiThread] Serialization Object went wrong" << std::endl;
                    exit(84);
                }
                std::string header = header_stream.str();

                // Merge
                std::vector<boost::asio::const_buffer> buffers;
                buffers.emplace_back(boost::asio::buffer(header));
                buffers.emplace_back(boost::asio::buffer(message_serialized));

                // Sending a long serialized message
                socket.send(boost::asio::buffer(header));
                socket.send(boost::asio::buffer(message_serialized));
                //_socket->send_to(buffers, *_endpoints.begin()); // TODO : send it only once (merge header + message)
            }
            else if (_protocolType == TEXT) {
                auto messageCast = static_cast<std::string>(message);
                socket.send(boost::asio::buffer(messageCast));
            }
        }

    private:
        boost::asio::io_context                         _io_context;
        std::list<boost::asio::ip::tcp::socket>         _sockets;
        std::unique_ptr<boost::asio::ip::tcp::acceptor> _acceptor;
        bool                _online;
        char                _inbound_header[8];
        size_t              _header_length;
        std::vector<char>   _inbound_data;
        ProtocolType        _protocolType;

    };
}

max_stars_repo_name: NicolasKeita/Apache-like


text:
#include "BucketToBufferGadget.h"
#include "hoNDArray_elemwise.h"
#include "hoNDArray_reductions.h"
#include "mri_core_data.h"
#include <boost/algorithm/string.hpp>

using BufferKey =  Gadgetron::BucketToBufferGadget::BufferKey;

namespace std {
    template<>
    struct less<BufferKey>{
        bool operator()(const BufferKey& idx1, const BufferKey& idx2) const {
            return std::tie(idx1.average,idx1.slice,idx1.contrast,idx1.phase,idx1.repetition,idx1.set,idx1.segment) <
                std::tie(idx2.average,idx2.slice,idx2.contrast,idx2.phase,idx2.repetition,idx2.set,idx2.segment);
        }
    };

    template<> struct equal_to<BufferKey>{
        bool operator()(const BufferKey& idx1, const BufferKey& idx2) const {
            return idx1.average == idx2.average
                   && idx1.slice == idx2.slice && idx1.contrast == idx2.contrast && idx1.phase == idx2.phase
                   && idx1.repetition == idx2.repetition && idx1.set == idx2.set && idx1.segment == idx2.segment;
        }
    };
}
namespace Gadgetron {
    namespace {

        IsmrmrdReconBit& getRBit(std::map<BufferKey, IsmrmrdReconData>& recon_data_buffers,
            const BufferKey& key, uint16_t espace) {

            // Look up the DataBuffered entry corresponding to this encoding space
            // create if needed and set the fields of view and matrix size
            if (recon_data_buffers[key].rbit_.size() < (espace + 1)) {
                recon_data_buffers[key].rbit_.resize(espace + 1);
            }

            return recon_data_buffers[key].rbit_[espace];
        }

    }

    void BucketToBufferGadget::process(Core::InputChannel<AcquisitionBucket>& input, Core::OutputChannel& out) {

        for (auto acq_bucket : input) {
            std::map<BufferKey, IsmrmrdReconData> recon_data_buffers;
            GDEBUG_STREAM("BUCKET_SIZE " << acq_bucket.data_.size() << " ESPACE " << acq_bucket.refstats_.size());
            // Iterate over the reference data of the bucket
            for (auto& acq : acq_bucket.ref_) {
                // Get a reference to the header for this acquisition

                const auto& acqhdr    = std::get<ISMRMRD::AcquisitionHeader>(acq);
                auto key              = getKey(acqhdr.idx);
                uint16_t espace       = acqhdr.encoding_space_ref;
                IsmrmrdReconBit& rbit = getRBit(recon_data_buffers, key, espace);
                if (!rbit.ref_) {
                    rbit.ref_ = makeDataBuffer(acqhdr, header.encoding[espace], acq_bucket.refstats_[espace], true);
                    rbit.ref_->sampling_ = createSamplingDescription(
                        header.encoding[espace], acq_bucket.refstats_[espace], acqhdr, true);
                }

                add_acquisition(*rbit.ref_, acq, header.encoding[espace], acq_bucket.refstats_[espace], true);

                // Stuff the data, header and trajectory into this data buffer
            }

            // Iterate over the reference data of the bucket
            for (auto& acq : acq_bucket.data_) {
                // Get a reference to the header for this acquisition

                const auto& acqhdr    = std::get<ISMRMRD::AcquisitionHeader>(acq);
                auto key              = getKey(acqhdr.idx);
                uint16_t espace       = acqhdr.encoding_space_ref;
                IsmrmrdReconBit& rbit = getRBit(recon_data_buffers, key, espace);
                if (rbit.data_.data_.empty()) {
                    rbit.data_ = makeDataBuffer(acqhdr, header.encoding[espace], acq_bucket.datastats_[espace], false);
                    rbit.data_.sampling_ = createSamplingDescription(
                        header.encoding[espace], acq_bucket.datastats_[espace], acqhdr, false);
                }

                add_acquisition(rbit.data_, acq, header.encoding[espace], acq_bucket.datastats_[espace], false);

                // Stuff the data, header and trajectory into this data buffer
            }

            // Send all the ReconData messages
            GDEBUG("End of bucket reached, sending out %d ReconData buffers\n", recon_data_buffers.size());

            for (auto& recon_data_buffer : recon_data_buffers) {
                if (acq_bucket.waveform_.empty())
                    out.push(recon_data_buffer.second);
                else
                    out.push(recon_data_buffer.second, acq_bucket.waveform_);
            }
        }
    }

    namespace {
        void clear(BucketToBufferGadget::Dimension dim, BufferKey& idx) {
            switch (dim) {

            case BucketToBufferGadget::Dimension::average: idx.average = 0; break;
            case BucketToBufferGadget::Dimension::contrast: idx.contrast = 0; break;
            case BucketToBufferGadget::Dimension::phase: idx.phase = 0; break;
            case BucketToBufferGadget::Dimension::repetition: idx.repetition = 0; break;
            case BucketToBufferGadget::Dimension::set: idx.set = 0; break;
            case BucketToBufferGadget::Dimension::segment: idx.segment = 0; break;
            case BucketToBufferGadget::Dimension::slice: break;
            case BucketToBufferGadget::Dimension::none: break;
            default: throw std::runtime_error("Invalid enum encountered");
            }
        }

        size_t getDimensionKey(BucketToBufferGadget::Dimension dim, const ISMRMRD::EncodingCounters& idx) {
            switch (dim) {

            case BucketToBufferGadget::Dimension::average: return idx.average;
            case BucketToBufferGadget::Dimension::contrast: return idx.contrast;
            case BucketToBufferGadget::Dimension::phase: return idx.phase;
            case BucketToBufferGadget::Dimension::repetition: return idx.repetition;
            case BucketToBufferGadget::Dimension::set: return idx.set;
            case BucketToBufferGadget::Dimension::segment: return idx.segment;
            case BucketToBufferGadget::Dimension::slice: return 0;
            case BucketToBufferGadget::Dimension::none: return 0;
            default: throw std::runtime_error("Invalid enum encountered");
            }
        }
    }

    BufferKey BucketToBufferGadget::getKey(const ISMRMRD::EncodingCounters& idx) const {
        BufferKey key = idx;
        clear(N_dimension, key);
        clear(S_dimension, key);
        if (!split_slices)
            key.slice = 0;
        if (ignore_segment)
            key.segment = 0;
        return key;
    }

    namespace {
        uint16_t getSizeFromDimension(BucketToBufferGadget::Dimension dimension, const AcquisitionBucketStats& stats) {
            switch (dimension) {
            case BucketToBufferGadget::Dimension::phase: return *stats.phase.rbegin() - *stats.phase.begin() + 1;
            case BucketToBufferGadget::Dimension::contrast:
                return *stats.contrast.rbegin() - *stats.contrast.begin() + 1;
            case BucketToBufferGadget::Dimension::repetition:
                return *stats.repetition.rbegin() - *stats.repetition.begin() + 1;
            case BucketToBufferGadget::Dimension::set: return *stats.set.rbegin() - *stats.set.begin() + 1;
            case BucketToBufferGadget::Dimension::segment:
            case BucketToBufferGadget::Dimension::average: return *stats.average.rbegin() - *stats.average.begin() + 1;
            case BucketToBufferGadget::Dimension::slice: return *stats.slice.rbegin() - *stats.slice.begin() + 1;
            case BucketToBufferGadget::Dimension::none:; return 1;
            default: throw std::runtime_error("Illegal enum value.");
            }
        }
    }

    IsmrmrdDataBuffered BucketToBufferGadget::makeDataBuffer(const ISMRMRD::AcquisitionHeader& acqhdr,
        ISMRMRD::Encoding encoding, const AcquisitionBucketStats& stats, bool forref) const {
        IsmrmrdDataBuffered buffer;

        // Allocate the reference data array
        // 7D,  fixed order [E0, E1, E2, CHA, N, S, LOC]
        // 11D, fixed order [E0, E1, E2, CHA, SLC, PHS, CON, REP, SET, SEG, AVE]
        const uint16_t NE0 = getNE0(acqhdr, encoding);

        uint16_t NE1 = getNE1(encoding, stats, forref);

        uint16_t NE2 = getNE2(encoding, stats, forref);

        uint16_t NCHA = acqhdr.active_channels;

        uint16_t NLOC = getNLOC(encoding, stats);

        uint16_t NN = getSizeFromDimension(N_dimension, stats);

        uint16_t NS = getSizeFromDimension(S_dimension, stats);

        GDEBUG_CONDITION_STREAM(verbose, "Data dimensions [RO E1 E2 CHA N S SLC] : ["
                                             << NE0 << " " << NE1 << " " << NE2 << " " << NCHA << " " << NN << " " << NS
                                             << " " << NLOC << "]");

        // Allocate the array for the data
        buffer.data_ = hoNDArray<std::complex<float>>(NE0, NE1, NE2, NCHA, NN, NS, NLOC);
        clear(&buffer.data_);

        // Allocate the array for the headers
        buffer.headers_ = hoNDArray<ISMRMRD::AcquisitionHeader>(NE1, NE2, NN, NS, NLOC);

        // Allocate the array for the trajectories
        uint16_t TRAJDIM = acqhdr.trajectory_dimensions;
        if (TRAJDIM > 0) {
            buffer.trajectory_ = hoNDArray<float>(TRAJDIM, NE0, NE1, NE2, NN, NS, NLOC);
            clear(*buffer.trajectory_);
        }
        return buffer;
    }

    uint16_t BucketToBufferGadget::getNLOC(
        const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats) const {
        uint16_t NLOC;
        if (split_slices) {
            NLOC = 1;
        } else {
            if (encoding.encodingLimits.slice.is_present()) {
                NLOC = encoding.encodingLimits.slice->maximum - encoding.encodingLimits.slice->minimum + 1;
            } else {
                NLOC = 1;
            }

            // if the AcquisitionAccumulateTriggerGadget sort by SLC, then the stats should be used to determine NLOC
            size_t NLOC_received = *stats.slice.rbegin() - *stats.slice.begin() + 1;
            if (NLOC_received < NLOC) {
                NLOC = NLOC_received;
            }
        }
        return NLOC;
    }
    uint16_t BucketToBufferGadget::getNE2(
        const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, bool forref) const {
        uint16_t NE2;
        if (((encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN))
            || (encoding.trajectory == ISMRMRD::TrajectoryType::EPI)) {
            if (encoding.parallelImaging) {
                if (forref
                    && (encoding.parallelImaging.get().calibrationMode.get() == "separate"
                        || encoding.parallelImaging.get().calibrationMode.get() == "external")) {
                    NE2 = encoding.encodingLimits.kspace_encoding_step_2->maximum
                          - encoding.encodingLimits.kspace_encoding_step_2->minimum + 1;
                } else {
                    NE2 = encoding.encodedSpace.matrixSize.z;
                }
            } else {
                if (encoding.encodingLimits.kspace_encoding_step_2.is_present()) {
                    NE2 = encoding.encodingLimits.kspace_encoding_step_2->maximum
                          - encoding.encodingLimits.kspace_encoding_step_2->minimum + 1;
                } else {
                    NE2 = encoding.encodedSpace.matrixSize.z;
                }
            }
        } else {
            if (encoding.encodingLimits.kspace_encoding_step_2.is_present()) {
                NE2 = encoding.encodingLimits.kspace_encoding_step_2->maximum
                      - encoding.encodingLimits.kspace_encoding_step_2->minimum + 1;
            } else {
                NE2 = *stats.kspace_encode_step_2.rbegin() - *stats.kspace_encode_step_2.begin() + 1;
            }
        }
        return NE2;
    }
    uint16_t BucketToBufferGadget::getNE1(
        const ISMRMRD::Encoding& encoding, const AcquisitionBucketStats& stats, bool forref) const {
        uint16_t NE1;
        if (((encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN))
            || (encoding.trajectory == ISMRMRD::TrajectoryType::EPI)) {
            if (encoding.parallelImaging) {
                if (forref
                    && (encoding.parallelImaging.get().calibrationMode.get() == "separate"
                        || encoding.parallelImaging.get().calibrationMode.get() == "external")) {
                    NE1 = *stats.kspace_encode_step_1.rbegin() - *stats.kspace_encode_step_1.begin() + 1;
                } else {
                    NE1 = encoding.encodedSpace.matrixSize.y;
                }
            } else {
                if (encoding.encodingLimits.kspace_encoding_step_1.is_present()) {
                    NE1 = encoding.encodingLimits.kspace_encoding_step_1->maximum
                          - encoding.encodingLimits.kspace_encoding_step_1->minimum + 1;
                } else {
                    NE1 = encoding.encodedSpace.matrixSize.y;
                }
            }
        } else {
            if (encoding.encodingLimits.kspace_encoding_step_1.is_present()) {
                NE1 = encoding.encodingLimits.kspace_encoding_step_1->maximum
                      - encoding.encodingLimits.kspace_encoding_step_1->minimum + 1;
            } else {
                NE1 = *stats.kspace_encode_step_1.rbegin() - *stats.kspace_encode_step_1.begin() + 1;
            }
        }
        return NE1;
    }
    uint16_t BucketToBufferGadget::getNE0(
        const ISMRMRD::AcquisitionHeader& acqhdr, const ISMRMRD::Encoding& encoding) const {
        uint16_t NE0;
        if (((encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN))
            || (encoding.trajectory == ISMRMRD::TrajectoryType::EPI)) {
            // if separate or external calibration mode, using the acq length for NE0
            if (encoding.parallelImaging) {
                NE0 = acqhdr.number_of_samples;
            } else {
                NE0 = acqhdr.number_of_samples - acqhdr.discard_pre - acqhdr.discard_post;
            }
        } else {
            NE0 = acqhdr.number_of_samples - acqhdr.discard_pre - acqhdr.discard_post;
        }
        return NE0;
    }
    namespace {
        template <class DIMSTRUCT> auto xyz_to_vector(const DIMSTRUCT& dimstruct) {
            std::array<decltype(dimstruct.x), 3> result = { dimstruct.x, dimstruct.y, dimstruct.z };
            return result;
        }
    }

    SamplingDescription BucketToBufferGadget::createSamplingDescription(const ISMRMRD::Encoding& encoding,
        const AcquisitionBucketStats& stats, const ISMRMRD::AcquisitionHeader& acqhdr, bool forref) const {
        auto sampling            = SamplingDescription();
        sampling.encoded_FOV_    = xyz_to_vector(encoding.encodedSpace.fieldOfView_mm);
        sampling.encoded_matrix_ = xyz_to_vector(encoding.encodedSpace.matrixSize);
        sampling.recon_FOV_      = xyz_to_vector(encoding.reconSpace.fieldOfView_mm);
        sampling.recon_matrix_   = xyz_to_vector(encoding.reconSpace.matrixSize);

        // For cartesian trajectories, assume that any oversampling has been removed.
        if (encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN) {
            sampling.encoded_FOV_[0]    = encoding.reconSpace.fieldOfView_mm.x;
            sampling.encoded_matrix_[0] = encoding.reconSpace.matrixSize.x;
        } else {
            sampling.encoded_FOV_[0]    = encoding.encodedSpace.fieldOfView_mm.x;
            sampling.encoded_matrix_[0] = encoding.encodedSpace.matrixSize.x;
        }

        // For cartesian trajectories, assume that any oversampling has been removed.
        if (((encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN))
            || (encoding.trajectory == ISMRMRD::TrajectoryType::EPI)) {
            sampling.sampling_limits_[0].min_    = acqhdr.discard_pre;
            sampling.sampling_limits_[0].max_    = acqhdr.number_of_samples - acqhdr.discard_post - 1;
            sampling.sampling_limits_[0].center_ = acqhdr.number_of_samples / 2;
        } else {
            sampling.sampling_limits_[0].min_    = 0;
            sampling.sampling_limits_[0].max_    = encoding.encodedSpace.matrixSize.x - 1;
            sampling.sampling_limits_[0].center_ = encoding.encodedSpace.matrixSize.x / 2;
        }

        // if the scan is cartesian
        if (((encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN)
                && (!forref || (forref && (encoding.parallelImaging.get().calibrationMode.get() == "embedded"))))
            || ((encoding.trajectory == ISMRMRD::TrajectoryType::EPI) && !forref)) {
            int16_t space_matrix_offset_E1 = 0;
            if (encoding.encodingLimits.kspace_encoding_step_1.is_present()) {
                space_matrix_offset_E1 = (int16_t)encoding.encodedSpace.matrixSize.y / 2
                                         - (int16_t)encoding.encodingLimits.kspace_encoding_step_1->center;
            }

            int16_t space_matrix_offset_E2 = 0;
            if (encoding.encodingLimits.kspace_encoding_step_2.is_present() && encoding.encodedSpace.matrixSize.z > 1) {
                space_matrix_offset_E2 = (int16_t)encoding.encodedSpace.matrixSize.z / 2
                                         - (int16_t)encoding.encodingLimits.kspace_encoding_step_2->center;
            }

            // E1
            sampling.sampling_limits_[1].min_
                = encoding.encodingLimits.kspace_encoding_step_1->minimum + space_matrix_offset_E1;
            sampling.sampling_limits_[1].max_
                = encoding.encodingLimits.kspace_encoding_step_1->maximum + space_matrix_offset_E1;
            sampling.sampling_limits_[1].center_ = sampling.encoded_matrix_[1] / 2;

            GADGET_CHECK_THROW(sampling.sampling_limits_[1].min_ < encoding.encodedSpace.matrixSize.y);
            GADGET_CHECK_THROW(sampling.sampling_limits_[1].max_ >= sampling.sampling_limits_[1].min_);
            GADGET_CHECK_THROW(sampling.sampling_limits_[1].center_ >= sampling.sampling_limits_[1].min_);
            GADGET_CHECK_THROW(sampling.sampling_limits_[1].center_ <= sampling.sampling_limits_[1].max_);

            // E2
            sampling.sampling_limits_[2].min_
                = encoding.encodingLimits.kspace_encoding_step_2->minimum + space_matrix_offset_E2;
            sampling.sampling_limits_[2].max_
                = encoding.encodingLimits.kspace_encoding_step_2->maximum + space_matrix_offset_E2;
            sampling.sampling_limits_[2].center_ = sampling.encoded_matrix_[2] / 2;

            GADGET_CHECK_THROW(sampling.sampling_limits_[2].min_ < encoding.encodedSpace.matrixSize.y);
            GADGET_CHECK_THROW(sampling.sampling_limits_[2].max_ >= sampling.sampling_limits_[2].min_);
            GADGET_CHECK_THROW(sampling.sampling_limits_[2].center_ >= sampling.sampling_limits_[2].min_);
            GADGET_CHECK_THROW(sampling.sampling_limits_[2].center_ <= sampling.sampling_limits_[2].max_);
        } else {
            sampling.sampling_limits_[1].min_    = encoding.encodingLimits.kspace_encoding_step_1->minimum;
            sampling.sampling_limits_[1].max_    = encoding.encodingLimits.kspace_encoding_step_1->maximum;
            sampling.sampling_limits_[1].center_ = encoding.encodingLimits.kspace_encoding_step_1->center;

            sampling.sampling_limits_[2].min_    = encoding.encodingLimits.kspace_encoding_step_2->minimum;
            sampling.sampling_limits_[2].max_    = encoding.encodingLimits.kspace_encoding_step_2->maximum;
            sampling.sampling_limits_[2].center_ = encoding.encodingLimits.kspace_encoding_step_2->center;
        }

        if (verbose) {
            GDEBUG_STREAM("Encoding space : "
                          << int(encoding.trajectory) << " - FOV : [ " << encoding.encodedSpace.fieldOfView_mm.x << " "
                          << encoding.encodedSpace.fieldOfView_mm.y << " " << encoding.encodedSpace.fieldOfView_mm.z
                          << " ] "
                          << " - Matris size : [ " << encoding.encodedSpace.matrixSize.x << " "
                          << encoding.encodedSpace.matrixSize.y << " " << encoding.encodedSpace.matrixSize.z << " ] ");

            GDEBUG_STREAM("Sampling limits : "
                          << "- RO : [ " << sampling.sampling_limits_[0].min_ << " "
                          << sampling.sampling_limits_[0].center_ << " " << sampling.sampling_limits_[0].max_
                          << " ] - E1 : [ " << sampling.sampling_limits_[1].min_ << " "
                          << sampling.sampling_limits_[1].center_ << " " << sampling.sampling_limits_[1].max_
                          << " ] - E2 : [ " << sampling.sampling_limits_[2].min_ << " "
                          << sampling.sampling_limits_[2].center_ << " " << sampling.sampling_limits_[2].max_ << " ]");
        }
        return sampling;
    }

    void BucketToBufferGadget::add_acquisition(IsmrmrdDataBuffered& dataBuffer, const Core::Acquisition& acq,
        ISMRMRD::Encoding encoding, const AcquisitionBucketStats& stats, bool forref) {

        // The acquisition header and data
        const auto& acqhdr  = std::get<ISMRMRD::AcquisitionHeader>(acq);
        const auto& acqdata = std::get<hoNDArray<std::complex<float>>>(acq);
        // we make one for the trajectory down below if we need it

        uint16_t NE0  = (uint16_t)dataBuffer.data_.get_size(0);
        uint16_t NE1  = (uint16_t)dataBuffer.data_.get_size(1);
        uint16_t NE2  = (uint16_t)dataBuffer.data_.get_size(2);
        uint16_t NCHA = (uint16_t)dataBuffer.data_.get_size(3);
        uint16_t NN   = (uint16_t)dataBuffer.data_.get_size(4);
        uint16_t NS   = (uint16_t)dataBuffer.data_.get_size(5);
        uint16_t NLOC = (uint16_t)dataBuffer.data_.get_size(6);

        const size_t slice_loc = split_slices || NLOC == 1 ? 0 : acqhdr.idx.slice;

        // Stuff the data
        uint16_t npts_to_copy = acqhdr.number_of_samples - acqhdr.discard_pre - acqhdr.discard_post;
        long long offset;
        if (encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN
            || encoding.trajectory == ISMRMRD::TrajectoryType::EPI) {
            if ((acqhdr.number_of_samples == dataBuffer.data_.get_size(0))
                && (acqhdr.center_sample
                    == acqhdr.number_of_samples / 2)) // acq has been corrected for center , e.g. by asymmetric handling
            {
                offset = acqhdr.discard_pre;
            } else {
                offset = (long long)dataBuffer.sampling_.sampling_limits_[0].center_ - (long long)acqhdr.center_sample;
            }
        } else {
            // TODO what about EPI with asymmetric readouts?
            // TODO any other sort of trajectory?
            offset = 0;
        }
        long long roffset = (long long)dataBuffer.data_.get_size(0) - npts_to_copy - offset;

        if ((offset < 0) | (roffset < 0)) {
            throw std::runtime_error("Acquired reference data does not fit into the reference data buffer.\n");
        }

        uint16_t NUsed = (uint16_t)getDimensionKey(N_dimension, acqhdr.idx);
        if (NUsed >= NN)
            NUsed = NN - 1;

        uint16_t SUsed = (uint16_t)getDimensionKey(S_dimension, acqhdr.idx);
        if (SUsed >= NS)
            SUsed = NS - 1;

        int16_t e1 = (int16_t)acqhdr.idx.kspace_encode_step_1;
        int16_t e2 = (int16_t)acqhdr.idx.kspace_encode_step_2;

        bool is_cartesian_sampling = (encoding.trajectory == ISMRMRD::TrajectoryType::CARTESIAN);
        bool is_epi_sampling       = (encoding.trajectory == ISMRMRD::TrajectoryType::EPI);
        if (is_cartesian_sampling || is_epi_sampling) {
            if (!forref || (forref && (encoding.parallelImaging.get().calibrationMode.get() == "embedded"))) {
                // compute the center offset for E1 and E2
                int16_t space_matrix_offset_E1 = 0;
                if (encoding.encodingLimits.kspace_encoding_step_1.is_present()) {
                    space_matrix_offset_E1 = (int16_t)encoding.encodedSpace.matrixSize.y / 2
                                             - (int16_t)encoding.encodingLimits.kspace_encoding_step_1->center;
                }

                int16_t space_matrix_offset_E2 = 0;
                if (encoding.encodingLimits.kspace_encoding_step_2.is_present()
                    && encoding.encodedSpace.matrixSize.z > 1) {
                    space_matrix_offset_E2 = (int16_t)encoding.encodedSpace.matrixSize.z / 2
                                             - (int16_t)encoding.encodingLimits.kspace_encoding_step_2->center;
                }

                // compute the used e1 and e2 indices and make sure they are in the valid range
                e1 = (int16_t)acqhdr.idx.kspace_encode_step_1 + space_matrix_offset_E1;
                e2 = (int16_t)acqhdr.idx.kspace_encode_step_2 + space_matrix_offset_E2;
            }

            // for external or separate mode, it is possible the starting numbers of ref lines are not zero, therefore
            // it is needed to subtract the staring ref line number because the ref array size is set up by the actual
            // number of lines acquired only assumption for external or separate ref line mode is that all ref lines are
            // numbered sequentially the acquisition order of ref line can be arbitrary
            if (forref
                && ((encoding.parallelImaging.get().calibrationMode.get() == "separate")
                    || (encoding.parallelImaging.get().calibrationMode.get() == "external"))) {
                if (*stats.kspace_encode_step_1.begin() > 0) {
                    e1 = acqhdr.idx.kspace_encode_step_1 - *stats.kspace_encode_step_1.begin();
                }

                if (*stats.kspace_encode_step_2.begin() > 0) {
                    e2 = acqhdr.idx.kspace_encode_step_2 - *stats.kspace_encode_step_2.begin();
                }
            }

            if (e1 < 0 || e1 >= (int16_t)NE1) {
                // if the incoming line is outside the encoding limits, something is wrong
                GADGET_CHECK_THROW(
                    acqhdr.idx.kspace_encode_step_1 >= encoding.encodingLimits.kspace_encoding_step_1->minimum
                    && acqhdr.idx.kspace_encode_step_1 <= encoding.encodingLimits.kspace_encoding_step_1->maximum);

                // if the incoming line is inside encoding limits but outside the encoded matrix, do not include the
                // data
                GWARN_STREAM(
                    "incoming readout "
                    << acqhdr.scan_counter
                    << " is inside the encoding limits, but outside the encoded matrix for kspace_encode_step_1 : "
                    << e1 << " out of " << NE1);
                return;
            }

            if (e2 < 0 || e2 >= (int16_t)NE2) {
                GADGET_CHECK_THROW(
                    acqhdr.idx.kspace_encode_step_2 >= encoding.encodingLimits.kspace_encoding_step_2->minimum
                    && acqhdr.idx.kspace_encode_step_2 <= encoding.encodingLimits.kspace_encoding_step_2->maximum);

                GWARN_STREAM(
                    "incoming readout "
                    << acqhdr.scan_counter
                    << " is inside the encoding limits, but outside the encoded matrix for kspace_encode_step_2 : "
                    << e2 << " out of " << NE2);
                return;
            }
        }

        std::complex<float>* pData = &dataBuffer.data_(offset, e1, e2, 0, NUsed, SUsed, slice_loc);

        for (uint16_t cha = 0; cha < NCHA; cha++) {
            auto dataptr = pData + cha * NE0 * NE1 * NE2;
            auto fromptr = &acqdata(acqhdr.discard_pre, cha);
            std::copy(fromptr, fromptr + npts_to_copy, dataptr);
        }

        dataBuffer.headers_(e1, e2, NUsed, SUsed, slice_loc) = acqhdr;

        if (acqhdr.trajectory_dimensions > 0) {

            const auto& acqtraj = *std::get<Core::optional<hoNDArray<float>>>(acq); // TODO do we need to check this?

            float* trajptr = &(*dataBuffer.trajectory_)(0, offset, e1, e2, NUsed, SUsed, slice_loc);
            auto* fromptr  = &acqtraj(0, acqhdr.discard_pre);
            std::copy(fromptr, fromptr + npts_to_copy * acqhdr.trajectory_dimensions, trajptr);
        }
    }
    BucketToBufferGadget::BucketToBufferGadget(const Core::Context& context, const Core::GadgetProperties& props)
        : ChannelGadget(context, props), header{ context.header } {}

    namespace {
        using Dimension = BucketToBufferGadget::Dimension;
        const std::map<std::string, BucketToBufferGadget::Dimension> dimension_from_name
            = { { "average", Dimension::average }, { "contrast", Dimension::contrast }, { "phase", Dimension::phase },
                  { "repetition", Dimension::repetition }, { "set", Dimension::set }, { "segment", Dimension::segment },
                  { "slice", Dimension::slice }, { "", Dimension::none }, { "none", Dimension::none }

              };
    }

    void from_string(const std::string& str, BucketToBufferGadget::Dimension& dim) {
        auto lower = str;
        boost::to_lower(lower);
        dim = dimension_from_name.at(lower);
    }

    GADGETRON_GADGET_EXPORT(BucketToBufferGadget)

}

max_stars_repo_name: roopchansinghv/gadgetron


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

/*
 *  basic_test.h
 *
 *  Created on: March 17, 2018
 *      Author: Narek Gharibyan <narekgharibyan@gmail.com>
 */

#include <exception>
#include <string>

#include <boost/filesystem/path.hpp>
#include <boost/test/unit_test.hpp>

#include "keyvi/vector/vector_types.h"

namespace keyvi {
namespace vector {

namespace {
template <typename VectorType>
struct TempVectorGenerator {
  TempVectorGenerator() {
    boost::filesystem::path temp_path = boost::filesystem::temp_directory_path();
    temp_path /= boost::filesystem::unique_path("vector-unit-test-%%%%-%%%%-%%%%-%%%%.kvv");
    filename = temp_path.string();
  }

  ~TempVectorGenerator() {
    if (boost::filesystem::exists(filename)) {
      boost::filesystem::remove(filename);
    }
  }

  void WriteToFile() { vector.WriteToFile(filename); }

  VectorType vector;
  std::string filename;
};

}  // namespace

BOOST_AUTO_TEST_SUITE(VectorTests)

BOOST_AUTO_TEST_CASE(string_test) {
  TempVectorGenerator<StringVectorGenerator> temp_vector;
  const size_t size = 100;

  for (size_t i = 0; i < size; ++i) {
    temp_vector.vector.PushBack(std::to_string(i));
  }

  temp_vector.WriteToFile();

  StringVector vector(temp_vector.filename);
  BOOST_CHECK_EQUAL(size, vector.Size());

  for (size_t i = 0; i < vector.Size(); ++i) {
    BOOST_CHECK_EQUAL(std::to_string(i), vector.Get(i));
  }
}

BOOST_AUTO_TEST_CASE(string_out_of_range) {
  TempVectorGenerator<StringVectorGenerator> temp_vector;
  const size_t size = 100;

  for (size_t i = 0; i < size; ++i) {
    temp_vector.vector.PushBack(std::to_string(i));
  }

  temp_vector.WriteToFile();

  StringVector vector(temp_vector.filename);
  BOOST_CHECK_THROW(vector.Get(size + 1), std::out_of_range);
}

BOOST_AUTO_TEST_CASE(json_test) {
  TempVectorGenerator<JsonVectorGenerator> temp_vector;
  const size_t size = 100;

  for (size_t i = 0; i < size; ++i) {
    temp_vector.vector.PushBack(std::to_string(i));
  }

  temp_vector.WriteToFile();

  JsonVector vector(temp_vector.filename);
  BOOST_CHECK_EQUAL(size, vector.Size());

  for (size_t i = 0; i < vector.Size(); ++i) {
    BOOST_CHECK_EQUAL(std::to_string(i), vector.Get(i));
  }
}

BOOST_AUTO_TEST_CASE(manifest) {
  TempVectorGenerator<JsonVectorGenerator> temp_vector;
  temp_vector.vector.SetManifest("Some manifest");
  temp_vector.WriteToFile();

  JsonVector vector(temp_vector.filename);

  BOOST_CHECK_EQUAL(vector.Manifest(), "Some manifest");
}

BOOST_AUTO_TEST_CASE(wrong_value_store) {
  TempVectorGenerator<JsonVectorGenerator> temp_vector;
  temp_vector.WriteToFile();

  BOOST_CHECK_THROW(std::move(StringVector(temp_vector.filename)), std::invalid_argument);
}

BOOST_AUTO_TEST_CASE(truncation) {
  TempVectorGenerator<JsonVectorGenerator> temp_vector;
  temp_vector.WriteToFile();

  // make sure file is okay
  JsonVector vector_normal(temp_vector.filename);

  std::ifstream in_stream(temp_vector.filename);
  in_stream.seekg(0, std::ios_base::end);
  const int file_size = in_stream.tellg();
  in_stream.seekg(0, std::ios_base::beg);

  std::vector<char> file_content(file_size);

  in_stream.read(file_content.data(), file_size);

  const std::string truncated_filename = temp_vector.filename + "-truncated";

  std::ofstream truncated_file(truncated_filename);
  truncated_file.write(file_content.data(), file_size - 1);
  truncated_file.close();

  BOOST_CHECK_THROW(std::move(JsonVector(truncated_filename)), std::invalid_argument);

  boost::filesystem::remove(truncated_filename);
}

BOOST_AUTO_TEST_SUITE_END()

}  // namespace vector
}  // namespace keyvi

max_stars_repo_name: vvucetic/keyvi

max_issues_repo_name: vvucetic/keyvi

max_forks_repo_name: vvucetic/keyvi