<commit_before>#include "kvazzupcontroller.h"

#include "statisticsinterface.h"

#include "common.h"

#include <QSettings>
#include <QHostAddress>

KvazzupController::KvazzupController():
    phaseReady_(0),
    conference_(SINGLE_CONNECTIONS),
    media_(),
    sip_(),
    window_(nullptr)
{}

void KvazzupController::init()
{
  window_.init(this);
  window_.show();

  sip_.init(this);

  QSettings settings("kvazzup.ini", QSettings::IniFormat);
  int autoConnect = settings.value("sip/AutoConnect").toInt();

  if(autoConnect == 1)
  {
    sip_.bindToServer();
  }

  // register the GUI signals indicating GUI changes to be handled approrietly in a system wide manner
  QObject::connect(&window_, SIGNAL(settingsChanged()), this, SLOT(updateSettings()));
  QObject::connect(&window_, SIGNAL(micStateSwitch()), this, SLOT(micState()));
  QObject::connect(&window_, SIGNAL(cameraStateSwitch()), this, SLOT(cameraState()));
  QObject::connect(&window_, SIGNAL(endCall()), this, SLOT(endTheCall()));
  QObject::connect(&window_, SIGNAL(closed()), this, SLOT(windowClosed()));

  QObject::connect(&window_, &CallWindow::callAccepted, this, &KvazzupController::userAcceptsCall);
  QObject::connect(&window_, &CallWindow::callRejected, this, &KvazzupController::userRejectsCall);
  QObject::connect(&window_, &CallWindow::callCancelled, this, &KvazzupController::userCancelsCall);

  stats_ = window_.createStatsWindow();

  media_.init(window_.getViewFactory(), stats_);
}

void KvazzupController::uninit()
{
  sip_.uninit();
  media_.uninit();
}

void KvazzupController::windowClosed()
{
  uninit();
}

uint32_t KvazzupController::callToParticipant(QString name, QString username, QString ip)
{
  QString ip_str = ip;

  Contact con;
  con.remoteAddress = ip_str;
  con.realName = name;
  con.username = username;

  //start negotiations for this connection
  qDebug() << "Session Initiation," << metaObject()->className()
           << ": Start Call," << metaObject()->className()
           << ": Initiated call starting to" << con.realName;

  return sip_.startCall(con);
}

uint32_t KvazzupController::chatWithParticipant(QString name, QString username,
                                                QString ip)
{
  qDebug() << "Chatting," << metaObject()->className()
           << ": Chatting with:" << name
           << '(' << username << ") at ip:" << ip << ": Chat not implemented yet";

  return 0;
}

void KvazzupController::outgoingCall(uint32_t sessionID, QString callee)
{
  window_.displayOutgoingCall(sessionID, callee);
  if(states_.find(sessionID) == states_.end())
  {
    states_[sessionID] = CALLINGTHEM;
    conference_ = SINGLE_CONNECTIONS;
  }
}

bool KvazzupController::incomingCall(uint32_t sessionID, QString caller)
{
  if(states_.find(sessionID) != states_.end())
  {
    qDebug() << "Incoming call," << metaObject()->className()
             << ": ERROR: Overwriting and existing session in the Kvazzup Core!";
  }

  QSettings settings("kvazzup.ini", QSettings::IniFormat);
  int autoAccept = settings.value("local/Auto-Accept").toInt();
  if(autoAccept == 1)
  {
    qDebug() << "Incoming call," << metaObject()->className()
             << ": Incoming call auto-accepted!";
    userAcceptsCall(sessionID);
    states_[sessionID] = CALLNEGOTIATING;
    return true;
  }
  else
  {
    window_.displayIncomingCall(sessionID, caller);
    states_[sessionID] = CALLRINGINGWITHUS;
  }
  return false;
}

void KvazzupController::callRinging(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end() && states_[sessionID] == CALLINGTHEM)
  {
    qDebug() << "Ringing," << metaObject()->className() << ": Our call is ringing!";
    window_.displayRinging(sessionID);
    states_[sessionID] = CALLRINGINWITHTHEM;
  }
  else
  {
    qDebug() << "Ringing," << metaObject()->className()
             << ": PEER ERROR: Got call ringing for nonexisting call:" << sessionID;
  }
}

void KvazzupController::peerAccepted(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLRINGINWITHTHEM || states_[sessionID] == CALLINGTHEM)
    {
      printDebug(DEBUG_NORMAL, this, DC_ACCEPT, "They accepted our call!");
      states_[sessionID] = CALLNEGOTIATING;
    }
    else
    {
      printDebug(DEBUG_PEER_ERROR, this, DC_ACCEPT,
                 "Got an accepted call even though we have not yet called them!");
    }
  }
  else
  {
    printDebug(DEBUG_PROGRAM_ERROR, this, DC_ACCEPT,
               "Peer accepted a session which is not in Core.");
  }
}

void KvazzupController::peerRejected(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLRINGINWITHTHEM)
    {
      qDebug() << "Rejection," << metaObject()->className()
               << ": Our call has been rejected!";
      removeSession(sessionID);
    }
    else
    {
      qDebug() << "Rejection," << metaObject()->className()
               << ": PEER ERROR: Got reject when we weren't calling them:"
               << states_[sessionID];
    }
  }
  else
  {
    qDebug() << "Rejection," << metaObject()->className()
             << ": PEER ERROR: Got reject for nonexisting call:" << sessionID;
    qDebug() << "Rejection," << metaObject()->className()
             << ": Number of ongoing sessions:" << states_.size();
  }
}

void KvazzupController::callNegotiated(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLNEGOTIATING || states_[sessionID] == CALLONGOING)
    {
      ++phaseReady_;

      printDebug(DEBUG_NORMAL, this, DC_NEGOTIATING, "Call negotiated.",
        {"sessionID", "Ready sessions", "Total sessions"},
        {QString::number(sessionID),
         QString::number(phaseReady_),
         QString::number(states_.size())});

      QSettings settings("kvazzup.ini", QSettings::IniFormat);
      int conference = settings.value("sip/conference").toInt();

      if (conference == 0 || states_.size() == 1)
      {
        createSingleCall(sessionID);
      }
      else
      {
        // can we proceed to next phase
        if (phaseReady_ == states_.size())
        {
          switch (conference_)
          {
            case SINGLE_CONNECTIONS:
            {
              conference_ = RECEIVE_PORTS;
              sip_.negotiateReceivePorts();
              phaseReady_ = 0;
              break;
            }
            case RECEIVE_PORTS:
            {
              conference_ = WHOLE_CONFERENCE;
              sip_.negotiateConference();
              phaseReady_ = 0;
              break;
            }
            case WHOLE_CONFERENCE:
            {
              for (auto session : states_)
              {
                createSingleCall(session.first);
              }
              conference_ = CONFERENCE_ACTIVE;
              break;
            }
            default:
            {
              printDebug(DEBUG_PROGRAM_ERROR, this, DC_NEGOTIATING,
                         "Conference negotiated, it was already active");
            }
          }
        }
      }
    }
    else
    {
       qDebug() << "Negotiation," << metaObject()->className()
                << ": PEER ERROR: Got call successful negotiation even though we are not there yet:"
                << states_[sessionID];
    }
  }
  else
  {
     qDebug() << "Negotiation," << metaObject()->className()
              << ": ERROR: This session does not exist in Call manager";
  }
}

void KvazzupController::createSingleCall(uint32_t sessionID)
{
  qDebug() << "Negotiation," << metaObject()->className()
           << ": Call has been agreed upon with peer:" << sessionID;

  std::shared_ptr<SDPMessageInfo> localSDP;
  std::shared_ptr<SDPMessageInfo> remoteSDP;

  sip_.getSDPs(sessionID,
               localSDP,
               remoteSDP);

  for (auto media : localSDP->media)
  {
    if (media.type == "video" && (media.flagAttributes.empty()
                                  || media.flagAttributes.at(0) == A_SENDRECV
                                  || media.flagAttributes.at(0) == A_RECVONLY))
    {
      window_.addVideoStream(sessionID);
    }
  }

  if(localSDP == nullptr || remoteSDP == nullptr)
  {
    printDebug(DEBUG_PROGRAM_ERROR, this, DC_ADD_MEDIA,
               "Failed to get SDP. Error should be detected earlier.");
    return;
  }

  media_.addParticipant(sessionID, remoteSDP, localSDP);
  states_[sessionID] = CALLONGOING;
}

void KvazzupController::callNegotiationFailed(uint32_t sessionID)
{
  // TODO: display a proper error for the user
  peerRejected(sessionID);
}

void KvazzupController::cancelIncomingCall(uint32_t sessionID)
{
  // TODO: display a proper message to the user that peer has cancelled their call
  removeSession(sessionID);
}

void KvazzupController::endCall(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end()
     && states_[sessionID] == CALLONGOING)
  {
    media_.removeParticipant(sessionID);
  }
  removeSession(sessionID);
}

void KvazzupController::registeredToServer()
{
  qDebug() << "Core," << metaObject()->className()
           << ": Got info, that we have been registered to SIP server.";
  // TODO: indicate to user in some small detail
}

void KvazzupController::registeringFailed()
{
  qDebug() << "Core," << metaObject()->className() << ": Failed to register";
  // TODO: indicate error to user
}

void KvazzupController::updateSettings()
{
  media_.updateSettings();
  //sip_.updateSettings(); // for blocking list
}

void KvazzupController::userAcceptsCall(uint32_t sessionID)
{
  qDebug() << "Core," << metaObject()->className() << ": Sending accept";
  sip_.acceptCall(sessionID);
  states_[sessionID] = CALLNEGOTIATING;
}

void KvazzupController::userRejectsCall(uint32_t sessionID)
{
  qDebug() << "Core," << metaObject()->className() << ": We have rejected their call";
  sip_.rejectCall(sessionID);
  removeSession(sessionID);
}

void KvazzupController::userCancelsCall(uint32_t sessionID)
{
  qDebug() << "Core," << metaObject()->className() << ": We have cancelled our call";
  sip_.cancelCall(sessionID);
  removeSession(sessionID);
}

void KvazzupController::endTheCall()
{
  qDebug() << "Core," << metaObject()->className()
           << ": End all call," << metaObject()->className()
           << ": End all calls button pressed";

  sip_.endAllCalls();
  media_.endAllCalls();
  window_.clearConferenceView();

  conference_ = SINGLE_CONNECTIONS;
  phaseReady_ = 0;
  states_.clear();
}

void KvazzupController::micState()
{
  window_.setMicState(media_.toggleMic());
}

void KvazzupController::cameraState()
{
  window_.setCameraState(media_.toggleCamera());
}

void KvazzupController::removeSession(uint32_t sessionID)
{
  window_.removeParticipant(sessionID);

  auto it = states_.find(sessionID);
  if(it != states_.end())
  {
    states_.erase(it);
  }
}
<commit_msg>feature(Controller): Remove previous media in conference negotiation.<commit_after>#include "kvazzupcontroller.h"

#include "statisticsinterface.h"

#include "common.h"

#include <QSettings>
#include <QHostAddress>

KvazzupController::KvazzupController():
    phaseReady_(0),
    conference_(SINGLE_CONNECTIONS),
    media_(),
    sip_(),
    window_(nullptr)
{}

void KvazzupController::init()
{
  window_.init(this);
  window_.show();

  sip_.init(this);

  QSettings settings("kvazzup.ini", QSettings::IniFormat);
  int autoConnect = settings.value("sip/AutoConnect").toInt();

  if(autoConnect == 1)
  {
    sip_.bindToServer();
  }

  // register the GUI signals indicating GUI changes to be handled approrietly in a system wide manner
  QObject::connect(&window_, SIGNAL(settingsChanged()), this, SLOT(updateSettings()));
  QObject::connect(&window_, SIGNAL(micStateSwitch()), this, SLOT(micState()));
  QObject::connect(&window_, SIGNAL(cameraStateSwitch()), this, SLOT(cameraState()));
  QObject::connect(&window_, SIGNAL(endCall()), this, SLOT(endTheCall()));
  QObject::connect(&window_, SIGNAL(closed()), this, SLOT(windowClosed()));

  QObject::connect(&window_, &CallWindow::callAccepted, this, &KvazzupController::userAcceptsCall);
  QObject::connect(&window_, &CallWindow::callRejected, this, &KvazzupController::userRejectsCall);
  QObject::connect(&window_, &CallWindow::callCancelled, this, &KvazzupController::userCancelsCall);

  stats_ = window_.createStatsWindow();

  media_.init(window_.getViewFactory(), stats_);
}

void KvazzupController::uninit()
{
  sip_.uninit();
  media_.uninit();
}

void KvazzupController::windowClosed()
{
  uninit();
}

uint32_t KvazzupController::callToParticipant(QString name, QString username, QString ip)
{
  QString ip_str = ip;

  Contact con;
  con.remoteAddress = ip_str;
  con.realName = name;
  con.username = username;

  //start negotiations for this connection
  qDebug() << "Session Initiation," << metaObject()->className()
           << ": Start Call," << metaObject()->className()
           << ": Initiated call starting to" << con.realName;

  return sip_.startCall(con);
}

uint32_t KvazzupController::chatWithParticipant(QString name, QString username,
                                                QString ip)
{
  qDebug() << "Chatting," << metaObject()->className()
           << ": Chatting with:" << name
           << '(' << username << ") at ip:" << ip << ": Chat not implemented yet";

  return 0;
}

void KvazzupController::outgoingCall(uint32_t sessionID, QString callee)
{
  window_.displayOutgoingCall(sessionID, callee);
  if(states_.find(sessionID) == states_.end())
  {
    states_[sessionID] = CALLINGTHEM;
    conference_ = SINGLE_CONNECTIONS;
  }
}

bool KvazzupController::incomingCall(uint32_t sessionID, QString caller)
{
  if(states_.find(sessionID) != states_.end())
  {
    qDebug() << "Incoming call," << metaObject()->className()
             << ": ERROR: Overwriting and existing session in the Kvazzup Core!";
  }

  QSettings settings("kvazzup.ini", QSettings::IniFormat);
  int autoAccept = settings.value("local/Auto-Accept").toInt();
  if(autoAccept == 1)
  {
    qDebug() << "Incoming call," << metaObject()->className()
             << ": Incoming call auto-accepted!";
    userAcceptsCall(sessionID);
    states_[sessionID] = CALLNEGOTIATING;
    return true;
  }
  else
  {
    window_.displayIncomingCall(sessionID, caller);
    states_[sessionID] = CALLRINGINGWITHUS;
  }
  return false;
}

void KvazzupController::callRinging(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end() && states_[sessionID] == CALLINGTHEM)
  {
    qDebug() << "Ringing," << metaObject()->className() << ": Our call is ringing!";
    window_.displayRinging(sessionID);
    states_[sessionID] = CALLRINGINWITHTHEM;
  }
  else
  {
    qDebug() << "Ringing," << metaObject()->className()
             << ": PEER ERROR: Got call ringing for nonexisting call:" << sessionID;
  }
}

void KvazzupController::peerAccepted(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLRINGINWITHTHEM || states_[sessionID] == CALLINGTHEM)
    {
      printDebug(DEBUG_NORMAL, this, DC_ACCEPT, "They accepted our call!");
      states_[sessionID] = CALLNEGOTIATING;
    }
    else
    {
      printDebug(DEBUG_PEER_ERROR, this, DC_ACCEPT,
                 "Got an accepted call even though we have not yet called them!");
    }
  }
  else
  {
    printDebug(DEBUG_PROGRAM_ERROR, this, DC_ACCEPT,
               "Peer accepted a session which is not in Core.");
  }
}

void KvazzupController::peerRejected(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLRINGINWITHTHEM)
    {
      qDebug() << "Rejection," << metaObject()->className()
               << ": Our call has been rejected!";
      removeSession(sessionID);
    }
    else
    {
      qDebug() << "Rejection," << metaObject()->className()
               << ": PEER ERROR: Got reject when we weren't calling them:"
               << states_[sessionID];
    }
  }
  else
  {
    qDebug() << "Rejection," << metaObject()->className()
             << ": PEER ERROR: Got reject for nonexisting call:" << sessionID;
    qDebug() << "Rejection," << metaObject()->className()
             << ": Number of ongoing sessions:" << states_.size();
  }
}

void KvazzupController::callNegotiated(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end())
  {
    if(states_[sessionID] == CALLNEGOTIATING || states_[sessionID] == CALLONGOING)
    {
      if (states_[sessionID] == CALLONGOING)
      {
        // we have to remove previous media so we do not double them.
        media_.removeParticipant(sessionID);
        window_.removeParticipant(sessionID);
      }

      ++phaseReady_;

      printDebug(DEBUG_NORMAL, this, DC_NEGOTIATING, "Call negotiated.",
        {"sessionID", "Ready sessions", "Total sessions"},
        {QString::number(sessionID),
         QString::number(phaseReady_),
         QString::number(states_.size())});

      QSettings settings("kvazzup.ini", QSettings::IniFormat);
      int conference = settings.value("sip/conference").toInt();

      if (conference == 0 || states_.size() == 1)
      {
        createSingleCall(sessionID);
      }
      else
      {
        // can we proceed to next phase
        if (phaseReady_ == states_.size())
        {
          switch (conference_)
          {
            case SINGLE_CONNECTIONS:
            {
              conference_ = RECEIVE_PORTS;
              sip_.negotiateReceivePorts();
              phaseReady_ = 0;
              break;
            }
            case RECEIVE_PORTS:
            {
              conference_ = WHOLE_CONFERENCE;
              sip_.negotiateConference();
              phaseReady_ = 0;
              break;
            }
            case WHOLE_CONFERENCE:
            {
              for (auto session : states_)
              {
                createSingleCall(session.first);
              }
              conference_ = CONFERENCE_ACTIVE;
              break;
            }
            default:
            {
              printDebug(DEBUG_PROGRAM_ERROR, this, DC_NEGOTIATING,
                         "Conference negotiated, it was already active");
            }
          }
        }
      }
    }
    else
    {
       qDebug() << "Negotiation," << metaObject()->className()
                << ": PEER ERROR: Got call successful negotiation "
                   "even though we are not there yet:"
                << states_[sessionID];
    }
  }
  else
  {
     qDebug() << "Negotiation," << metaObject()->className()
              << ": ERROR: This session does not exist in Call manager";
  }
}

void KvazzupController::createSingleCall(uint32_t sessionID)
{
  qDebug() << "Negotiation," << metaObject()->className()
           << ": Call has been agreed upon with peer:" << sessionID;

  std::shared_ptr<SDPMessageInfo> localSDP;
  std::shared_ptr<SDPMessageInfo> remoteSDP;

  sip_.getSDPs(sessionID,
               localSDP,
               remoteSDP);

  for (auto media : localSDP->media)
  {
    if (media.type == "video" && (media.flagAttributes.empty()
                                  || media.flagAttributes.at(0) == A_SENDRECV
                                  || media.flagAttributes.at(0) == A_RECVONLY))
    {
      window_.addVideoStream(sessionID);
    }
  }

  if(localSDP == nullptr || remoteSDP == nullptr)
  {
    printDebug(DEBUG_PROGRAM_ERROR, this, DC_ADD_MEDIA,
               "Failed to get SDP. Error should be detected earlier.");
    return;
  }

  media_.addParticipant(sessionID, remoteSDP, localSDP);
  states_[sessionID] = CALLONGOING;
}

void KvazzupController::callNegotiationFailed(uint32_t sessionID)
{
  // TODO: display a proper error for the user
  peerRejected(sessionID);
}

void KvazzupController::cancelIncomingCall(uint32_t sessionID)
{
  // TODO: display a proper message to the user that peer has cancelled their call
  removeSession(sessionID);
}

void KvazzupController::endCall(uint32_t sessionID)
{
  if(states_.find(sessionID) != states_.end()
     && states_[sessionID] == CALLONGOING)
  {
    media_.removeParticipant(sessionID);
  }
  removeSession(sessionID);
}

void KvazzupController::registeredToServer()
{
  qDebug() << "Core," << metaObject()->className()
           << ": Got info, that we have been registered to SIP server.";
  // TODO: indicate to user in some small detail
}

void KvazzupController::registeringFailed()
{
  qDebug() << "Core," << metaObject()->className() << ": Failed to register";
  // TODO: indicate error to user
}

void KvazzupController::updateSettings()
{
  media_.updateSettings();
  //sip_.updateSettings(); // for blocking list
}

void KvazzupController::userAcceptsCall(uint32_t sessionID)
{
  qDebug() << "Core," << metaObject()->className() << ": Sending accept";
  sip_.acceptCall(sessionID);
  states_[sessionID] = CALLNEGOTIATING;
}

void KvazzupController::userRejectsCall(uint32_t sessionID)
{
  qDebug() << "Core," << metaObject()->className() << ": We have rejected their call";
  sip_.rejectCall(sessionID);
  removeSession(sessionID);
}

void KvazzupController::userCancelsCall(uint32_t sessionID)
{
  qDebug() << "Core," << metaObject()->className() << ": We have cancelled our call";
  sip_.cancelCall(sessionID);
  removeSession(sessionID);
}

void KvazzupController::endTheCall()
{
  qDebug() << "Core," << metaObject()->className()
           << ": End all call," << metaObject()->className()
           << ": End all calls button pressed";

  sip_.endAllCalls();
  media_.endAllCalls();
  window_.clearConferenceView();

  conference_ = SINGLE_CONNECTIONS;
  phaseReady_ = 0;
  states_.clear();
}

void KvazzupController::micState()
{
  window_.setMicState(media_.toggleMic());
}

void KvazzupController::cameraState()
{
  window_.setCameraState(media_.toggleCamera());
}

void KvazzupController::removeSession(uint32_t sessionID)
{
  window_.removeParticipant(sessionID);

  auto it = states_.find(sessionID);
  if(it != states_.end())
  {
    states_.erase(it);
  }
}
<|endoftext|>


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

#if defined(HAVE_CONFIG_H)
#include "config/navcoin-config.h"
#endif

#include "utiltime.h"

#include <chrono>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>

using namespace std;

static int64_t nMockTime = 0; //!< For unit testing
static int64_t nNtpTimeOffset = 0;

int64_t GetTime()
{
    if (nMockTime) return nMockTime;

    time_t now = time(NULL);
    assert(now > 0);
    return now - GetNtpTimeOffset();
}

int64_t GetSteadyTime()
{
    auto now = std::chrono::steady_clock::now();
    auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
    assert(millisecs.count() > 0);
    return millisecs.count()/1000;
}

void SetMockTime(int64_t nMockTimeIn)
{
    nMockTime = nMockTimeIn;
}

int64_t GetTimeMillis()
{
    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
    assert(now > 0);
    return now - (GetNtpTimeOffset() * 1000);
}

int64_t GetTimeMicros()
{
    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
    assert(now > 0);
    return now - (GetNtpTimeOffset() * 1000  * 1000);
}

/** Return a time useful for the debug log */
int64_t GetLogTimeMicros()
{
    if (nMockTime) return nMockTime*1000000;

    return GetTimeMicros();
}

void MilliSleep(int64_t n)
{

/**
 * Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
 * until fixed in 1.52. Use the deprecated sleep method for the broken case.
 * See: https://svn.boost.org/trac/boost/ticket/7238
 */
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
    boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
#elif defined(HAVE_WORKING_BOOST_SLEEP)
    boost::this_thread::sleep(boost::posix_time::milliseconds(n));
#else
//should never get here
#error missing boost sleep implementation
#endif
}

std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
{
    // std::locale takes ownership of the pointer
    std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat));
    std::stringstream ss;
    ss.imbue(loc);
    ss << boost::posix_time::from_time_t(nTime);
    return ss.str();
}

int64_t GetNtpTimeOffset()
{
    return nNtpTimeOffset;
}

void SetNtpTimeOffset(uint64_t nTimeOffsetIn)
{
    nNtpTimeOffset = nTimeOffsetIn;
    return true;
}
<commit_msg>fix return<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#if defined(HAVE_CONFIG_H)
#include "config/navcoin-config.h"
#endif

#include "utiltime.h"

#include <chrono>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>

using namespace std;

static int64_t nMockTime = 0; //!< For unit testing
static int64_t nNtpTimeOffset = 0;

int64_t GetTime()
{
    if (nMockTime) return nMockTime;

    time_t now = time(NULL);
    assert(now > 0);
    return now - GetNtpTimeOffset();
}

int64_t GetSteadyTime()
{
    auto now = std::chrono::steady_clock::now();
    auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
    assert(millisecs.count() > 0);
    return millisecs.count()/1000;
}

void SetMockTime(int64_t nMockTimeIn)
{
    nMockTime = nMockTimeIn;
}

int64_t GetTimeMillis()
{
    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
    assert(now > 0);
    return now - (GetNtpTimeOffset() * 1000);
}

int64_t GetTimeMicros()
{
    int64_t now = (boost::posix_time::microsec_clock::universal_time() -
                   boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
    assert(now > 0);
    return now - (GetNtpTimeOffset() * 1000  * 1000);
}

/** Return a time useful for the debug log */
int64_t GetLogTimeMicros()
{
    if (nMockTime) return nMockTime*1000000;

    return GetTimeMicros();
}

void MilliSleep(int64_t n)
{

/**
 * Boost's sleep_for was uninterruptable when backed by nanosleep from 1.50
 * until fixed in 1.52. Use the deprecated sleep method for the broken case.
 * See: https://svn.boost.org/trac/boost/ticket/7238
 */
#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
    boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
#elif defined(HAVE_WORKING_BOOST_SLEEP)
    boost::this_thread::sleep(boost::posix_time::milliseconds(n));
#else
//should never get here
#error missing boost sleep implementation
#endif
}

std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
{
    // std::locale takes ownership of the pointer
    std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat));
    std::stringstream ss;
    ss.imbue(loc);
    ss << boost::posix_time::from_time_t(nTime);
    return ss.str();
}

int64_t GetNtpTimeOffset()
{
    return nNtpTimeOffset;
}

void SetNtpTimeOffset(uint64_t nTimeOffsetIn)
{
    nNtpTimeOffset = nTimeOffsetIn;
}
<|endoftext|>


<commit_before>/*! \file helpers.hpp
    \brief Internal helper functionality
    \ingroup Internal */
/*
  Copyright (c) 2014, Randolph Voorhies, Shane Grant
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
      * Redistributions of source code must retain the above copyright
        notice, this list 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 cereal 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 RANDOLPH VOORHIES OR SHANE GRANT 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.
*/
#ifndef CEREAL_DETAILS_HELPERS_HPP_
#define CEREAL_DETAILS_HELPERS_HPP_

#include <type_traits>
#include <cstdint>
#include <utility>
#include <memory>
#include <unordered_map>
#include <stdexcept>

#include <cereal/macros.hpp>
#include <cereal/details/static_object.hpp>

namespace cereal
{
  // ######################################################################
  //! An exception class thrown when things go wrong at runtime
  /*! @ingroup Utility */
  struct Exception : public std::runtime_error
  {
    Exception( const std::string & what_ ) : std::runtime_error(what_) {}
    Exception( const char * what_ ) : std::runtime_error(what_) {}
  };

  // ######################################################################
  //! The size type used by cereal
  /*! To ensure compatability between 32, 64, etc bit machines, we need to use
   * a fixed size type instead of size_t, which may vary from machine to
   * machine. */
  using size_type = uint64_t;

  // forward decls
  class BinaryOutputArchive;
  class BinaryInputArchive;

  // ######################################################################
  namespace detail
  {
    struct NameValuePairCore {};
  }

  //! For holding name value pairs
  /*! This pairs a name (some string) with some value such that an archive
      can potentially take advantage of the pairing.

      In serialization functions, NameValuePairs are usually created like so:
      @code{.cpp}
      struct MyStruct
      {
        int a, b, c, d, e;

        template<class Archive>
        void serialize(Archive & archive)
        {
          archive( CEREAL_NVP(a),
                   CEREAL_NVP(b),
                   CEREAL_NVP(c),
                   CEREAL_NVP(d),
                   CEREAL_NVP(e) );
        }
      };
      @endcode

      Alternatively, you can give you data members custom names like so:
      @code{.cpp}
      struct MyStruct
      {
        int a, b, my_embarrassing_variable_name, d, e;

        template<class Archive>
        void serialize(Archive & archive)
        {
          archive( CEREAL_NVP(a),
                   CEREAL_NVP(b),
                   cereal::make_nvp("var", my_embarrassing_variable_name) );
                   CEREAL_NVP(d),
                   CEREAL_NVP(e) );
        }
      };
      @endcode

      There is a slight amount of overhead to creating NameValuePairs, so there
      is a third method which will elide the names when they are not needed by
      the Archive:

      @code{.cpp}
      struct MyStruct
      {
        int a, b;

        template<class Archive>
        void serialize(Archive & archive)
        {
          archive( cereal::make_nvp<Archive>(a),
                   cereal::make_nvp<Archive>(b) );
        }
      };
      @endcode

      This third method is generally only used when providing generic type
      support.  Users writing their own serialize functions will normally
      explicitly control whether they want to use NVPs or not.

      @internal */
  template <class T>
  class NameValuePair : detail::NameValuePairCore
  {
    private:
      // If we get passed an RValue, we'll just make a local copy if it here
      // otherwise, we store a reference.  If we were passed an array, don't
      // decay the type - keep it as an array, and then proceed as normal
      // with the RValue business
      using DT = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
                                           typename std::remove_cv<T>::type,
                                           typename std::decay<T>::type>::type;
      using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
                                             DT,
                                             typename std::add_lvalue_reference<DT>::type>::type;
      // prevent nested nvps
      static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
                     "Cannot pair a name to a NameValuePair" );

    public:
      //! Constructs a new NameValuePair
      /*! @param n The name of the pair
          @param v The value to pair.  Ideally this should be an l-value reference so that
                   the value can be both loaded and saved to.  If you pass an r-value reference,
                   the NameValuePair will store a copy of it instead of a reference.  Thus you should
                   only pass r-values in cases where this makes sense, such as the result of some
                   size() call.  In either case, any constness will be stripped away
      @internal */
      NameValuePair( char const * n, T && v ) : name(n), value(const_cast<Type>(v)) {}

      char const * name;
      Type value;
  };

  //! A specialization of make_nvp<> that simply forwards the value for binary archives
  /*! @relates NameValuePair
      @internal */
  template<class Archive, class T> inline
  typename
  std::enable_if<std::is_same<Archive, ::cereal::BinaryInputArchive>::value ||
                 std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
  T && >::type
  make_nvp( const char *, T && value )
  {
    return std::forward<T>(value);
  }

  //! A specialization of make_nvp<> that actually creates an nvp for non-binary archives
  /*! @relates NameValuePair
      @internal */
  template<class Archive, class T> inline
  typename
  std::enable_if<!std::is_same<Archive, ::cereal::BinaryInputArchive>::value &&
                 !std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
  NameValuePair<T> >::type
  make_nvp( const char * name, T && value)
  {
    return {name, std::forward<T>(value)};
  }

  //! Convenience for creating a templated NVP
  /*! For use in inteneral generic typing functions which have an
      Archive type declared
      @internal */
#define _CEREAL_NVP(name, value) ::cereal::make_nvp<Archive>(name, value)

  // ######################################################################
  //! A wrapper around data that can be serialized in a binary fashion
  /*! This class is used to demarcate data that can safely be serialized
      as a binary chunk of data.  Individual archives can then choose how
      best represent this during serialization.

      @internal */
  template <class T>
  struct BinaryData
  {
    //! Internally store the pointer as a void *, keeping const if created with
    //! a const pointer
    using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
                                         const void *,
                                         void *>::type;

    BinaryData( T && d, uint64_t s ) : data(d), size(s) {}

    PT data;   //!< pointer to beginning of data
    uint64_t size; //!< size in bytes
  };

  // ######################################################################
  namespace detail
  {
    // base classes for type checking
    struct OutputArchiveBase {};
    struct InputArchiveBase {};

    // forward decls for polymorphic support
    template <class Archive, class T> struct polymorphic_serialization_support;
    struct adl_tag;

    // used during saving pointers
    static const int32_t msb_32bit = 0x80000000;
    static const int32_t msb2_32bit = 0x40000000;
  }

  // ######################################################################
  //! A wrapper around size metadata
  /*! This class provides a way for archives to have more flexibility over how
      they choose to serialize size metadata for containers.  For some archive
      types, the size may be implicitly encoded in the output (e.g. JSON) and
      not need an explicit entry.  Specializing serialize or load/save for
      your archive and SizeTags allows you to choose what happens.

      @internal */
  template <class T>
  class SizeTag
  {
    private:
      // If we get passed an RValue, we'll just make a local copy if it here
      // otherwise, we store a reference
      using DT = typename std::decay<T>::type;
      using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
                                             DT,
                                             typename std::add_lvalue_reference<DT>::type>::type;

    public:
      SizeTag( T && sz ) : size(const_cast<Type>(sz)) {}

      Type size;
  };

  // ######################################################################
  //! A wrapper around a key and value for serializing data into maps.
  /*! This class just provides a grouping of keys and values into a struct for
      human readable archives. For example, XML archives will use this wrapper
      to write maps like so:

      @code{.xml}
      <mymap>
        <item0>
          <key>MyFirstKey</key>
          <value>MyFirstValue</value>
        </item0>
        <item1>
          <key>MySecondKey</key>
          <value>MySecondValue</value>
        </item1>
      </mymap>
      @endcode

      \sa make_map_item
      @internal */
  template <class Key, class Value>
  struct MapItem
  {
    using DecayKey = typename std::decay<Key>::type;
    using KeyType = typename std::conditional<
      std::is_rvalue_reference<Key>::value,
      DecayKey,
      typename std::add_lvalue_reference<DecayKey>::type>::type;

    using DecayValue = typename std::decay<Value>::type;
    using ValueType =  typename std::conditional<
      std::is_rvalue_reference<Value>::value,
      DecayValue,
      typename std::add_lvalue_reference<DecayValue>::type>::type;

    //! Construct a MapItem from a key and a value
    /*! @internal */
    MapItem( Key && key_, Value && value_ ) : key(const_cast<KeyType>(key_)), value(const_cast<ValueType>(value_)) {}

    KeyType key;
    ValueType value;

    //! Serialize the MapItem with the NVPs "key" and "value"
    template <class Archive> inline
    void CEREAL_SERIALIZE_FUNCTION_NAME(Archive & archive)
    {
      archive( make_nvp<Archive>("key",   key),
               make_nvp<Archive>("value", value) );
    }
  };

  //! Create a MapItem so that human readable archives will group keys and values together
  /*! @internal
      @relates MapItem */
  template <class KeyType, class ValueType> inline
  MapItem<KeyType, ValueType> make_map_item(KeyType && key, ValueType && value)
  {
    return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
  }

  namespace detail
  {
    // ######################################################################
    //! Holds all registered version information
    struct Versions
    {
      std::unordered_map<std::size_t, std::uint32_t> mapping;
    }; // struct Versions

    //! Version information class
    /*! This is the base case for classes that have not been explicitly
        registered */
    template <class T> struct Version
    {
      static const std::uint32_t version = 0;
      // we don't need to explicitly register these types since they
      // always get a version number of 0
    };

    #ifdef CEREAL_FUTURE_EXPERIMENTAL
    // ######################################################################
    //! A class that can store any type
    /*! This is inspired by boost::any and is intended to be a very light-weight
        replacement for internal use only.

        This class is only here as a candidate for issue #46 (see github) and
        should be considered unsupported until a future version of cereal.
        */
    class Any
    {
      private:
        //! Convenience alias for decay
        template <class T>
        using ST = typename std::decay<T>::type;

        struct Base
        {
          virtual ~Base() {}
          virtual std::unique_ptr<Base> clone() const = 0;
        };

        template <class T>
        struct Derived : Base
        {
          template <class U>
          Derived( U && data ) : value( std::forward<U>( data ) ) {}

          std::unique_ptr<Base> clone() const
          {
            return std::unique_ptr<Base>( new Derived<T>( value ) );
          }

          T value;
        };

      public:
        //! Construct from any type
        template <class T> inline
        Any( T && data ) :
          itsPtr( new Derived<ST<T>>( std::forward<T>( data ) ) )
        { }

        //! Convert to any type, if possible
        /*! Attempts to perform the conversion if possible,
            otherwise throws an exception.

            @throw Exception if conversion is not possible (see get() for more info)
            @tparam The requested type to convert to */
        template <class T> inline
        operator T()
        {
          return get<ST<T>>();
        }

        Any() : itsPtr() {}
        Any( Any & other ) : itsPtr( other.clone() ) {}
        Any( Any const & other ) : itsPtr( other.clone() ) {}
        Any( Any && other ) : itsPtr( std::move( other.itsPtr ) ) {}

        Any & operator=( Any const & other )
        {
          if( itsPtr == other.itsPtr ) return *this;

          auto cloned = other.clone();
          itsPtr = std::move( cloned );

          return *this;
        }

        Any & operator=( Any && other )
        {
          if( itsPtr == other.itsPtr ) return *this;

          itsPtr = std::move( other.itsPtr );

          return *this;
        }

      protected:
        //! Get the contained type as type T
        /*! @tparam T The requested type to convert to
            @return The type converted to T
            @throw Exception if conversion is impossible */
        template <class T>
        ST<T> & get()
        {
          auto * derived = dynamic_cast<Derived<ST<T>> *>( itsPtr.get() );

          if( !derived )
            throw ::cereal::Exception( "Invalid conversion requested on ASDFA" );

          return derived->value;
        }

        //! Clones the held data if it exists
        std::unique_ptr<Base> clone() const
        {
          if( itsPtr ) return itsPtr->clone();
          else return {};
        }

      private:
        std::unique_ptr<Base> itsPtr;
    }; // struct Any
    #endif // CEREAL_FUTURE_EXPERIMENTAL
  } // namespace detail
} // namespace cereal

#endif // CEREAL_DETAILS_HELPERS_HPP_
<commit_msg>SizeTag and Map changes for #96<commit_after>/*! \file helpers.hpp
    \brief Internal helper functionality
    \ingroup Internal */
/*
  Copyright (c) 2014, Randolph Voorhies, Shane Grant
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:
      * Redistributions of source code must retain the above copyright
        notice, this list 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 cereal 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 RANDOLPH VOORHIES OR SHANE GRANT 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.
*/
#ifndef CEREAL_DETAILS_HELPERS_HPP_
#define CEREAL_DETAILS_HELPERS_HPP_

#include <type_traits>
#include <cstdint>
#include <utility>
#include <memory>
#include <unordered_map>
#include <stdexcept>

#include <cereal/macros.hpp>
#include <cereal/details/static_object.hpp>

namespace cereal
{
  // ######################################################################
  //! An exception class thrown when things go wrong at runtime
  /*! @ingroup Utility */
  struct Exception : public std::runtime_error
  {
    Exception( const std::string & what_ ) : std::runtime_error(what_) {}
    Exception( const char * what_ ) : std::runtime_error(what_) {}
  };

  // ######################################################################
  //! The size type used by cereal
  /*! To ensure compatability between 32, 64, etc bit machines, we need to use
   * a fixed size type instead of size_t, which may vary from machine to
   * machine. */
  using size_type = uint64_t;

  // forward decls
  class BinaryOutputArchive;
  class BinaryInputArchive;

  // ######################################################################
  namespace detail
  {
    struct NameValuePairCore {};
  }

  //! For holding name value pairs
  /*! This pairs a name (some string) with some value such that an archive
      can potentially take advantage of the pairing.

      In serialization functions, NameValuePairs are usually created like so:
      @code{.cpp}
      struct MyStruct
      {
        int a, b, c, d, e;

        template<class Archive>
        void serialize(Archive & archive)
        {
          archive( CEREAL_NVP(a),
                   CEREAL_NVP(b),
                   CEREAL_NVP(c),
                   CEREAL_NVP(d),
                   CEREAL_NVP(e) );
        }
      };
      @endcode

      Alternatively, you can give you data members custom names like so:
      @code{.cpp}
      struct MyStruct
      {
        int a, b, my_embarrassing_variable_name, d, e;

        template<class Archive>
        void serialize(Archive & archive)
        {
          archive( CEREAL_NVP(a),
                   CEREAL_NVP(b),
                   cereal::make_nvp("var", my_embarrassing_variable_name) );
                   CEREAL_NVP(d),
                   CEREAL_NVP(e) );
        }
      };
      @endcode

      There is a slight amount of overhead to creating NameValuePairs, so there
      is a third method which will elide the names when they are not needed by
      the Archive:

      @code{.cpp}
      struct MyStruct
      {
        int a, b;

        template<class Archive>
        void serialize(Archive & archive)
        {
          archive( cereal::make_nvp<Archive>(a),
                   cereal::make_nvp<Archive>(b) );
        }
      };
      @endcode

      This third method is generally only used when providing generic type
      support.  Users writing their own serialize functions will normally
      explicitly control whether they want to use NVPs or not.

      @internal */
  template <class T>
  class NameValuePair : detail::NameValuePairCore
  {
    private:
      // If we get passed an RValue, we'll just make a local copy if it here
      // otherwise, we store a reference.  If we were passed an array, don't
      // decay the type - keep it as an array, and then proceed as normal
      // with the RValue business
      using DT = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
                                           typename std::remove_cv<T>::type,
                                           typename std::decay<T>::type>::type;
      using Type = typename std::conditional<std::is_rvalue_reference<T>::value,
                                             DT,
                                             typename std::add_lvalue_reference<DT>::type>::type;
      // prevent nested nvps
      static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
                     "Cannot pair a name to a NameValuePair" );

    public:
      //! Constructs a new NameValuePair
      /*! @param n The name of the pair
          @param v The value to pair.  Ideally this should be an l-value reference so that
                   the value can be both loaded and saved to.  If you pass an r-value reference,
                   the NameValuePair will store a copy of it instead of a reference.  Thus you should
                   only pass r-values in cases where this makes sense, such as the result of some
                   size() call.  In either case, any constness will be stripped away
      @internal */
      NameValuePair( char const * n, T && v ) : name(n), value(const_cast<Type>(v)) {}

      char const * name;
      Type value;
  };

  //! A specialization of make_nvp<> that simply forwards the value for binary archives
  /*! @relates NameValuePair
      @internal */
  template<class Archive, class T> inline
  typename
  std::enable_if<std::is_same<Archive, ::cereal::BinaryInputArchive>::value ||
                 std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
  T && >::type
  make_nvp( const char *, T && value )
  {
    return std::forward<T>(value);
  }

  //! A specialization of make_nvp<> that actually creates an nvp for non-binary archives
  /*! @relates NameValuePair
      @internal */
  template<class Archive, class T> inline
  typename
  std::enable_if<!std::is_same<Archive, ::cereal::BinaryInputArchive>::value &&
                 !std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
  NameValuePair<T> >::type
  make_nvp( const char * name, T && value)
  {
    return {name, std::forward<T>(value)};
  }

  //! Convenience for creating a templated NVP
  /*! For use in inteneral generic typing functions which have an
      Archive type declared
      @internal */
#define _CEREAL_NVP(name, value) ::cereal::make_nvp<Archive>(name, value)

  // ######################################################################
  //! A wrapper around data that can be serialized in a binary fashion
  /*! This class is used to demarcate data that can safely be serialized
      as a binary chunk of data.  Individual archives can then choose how
      best represent this during serialization.

      @internal */
  template <class T>
  struct BinaryData
  {
    //! Internally store the pointer as a void *, keeping const if created with
    //! a const pointer
    using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
                                         const void *,
                                         void *>::type;

    BinaryData( T && d, uint64_t s ) : data(d), size(s) {}

    PT data;   //!< pointer to beginning of data
    uint64_t size; //!< size in bytes
  };

  // ######################################################################
  namespace detail
  {
    // base classes for type checking
    struct OutputArchiveBase {};
    struct InputArchiveBase {};

    // forward decls for polymorphic support
    template <class Archive, class T> struct polymorphic_serialization_support;
    struct adl_tag;

    // used during saving pointers
    static const int32_t msb_32bit = 0x80000000;
    static const int32_t msb2_32bit = 0x40000000;
  }

  // ######################################################################
  //! A wrapper around size metadata
  /*! This class provides a way for archives to have more flexibility over how
      they choose to serialize size metadata for containers.  For some archive
      types, the size may be implicitly encoded in the output (e.g. JSON) and
      not need an explicit entry.  Specializing serialize or load/save for
      your archive and SizeTags allows you to choose what happens.

      @internal */
  template <class T>
  class SizeTag
  {
    private:
      // Store a reference if passed an lvalue reference, otherwise
      // make a copy of the data
      using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
                                             T,
                                             typename std::decay<T>::type>::type;

    public:
      SizeTag( T && sz ) : size(sz) {}

      Type size;
  };

  // ######################################################################
  //! A wrapper around a key and value for serializing data into maps.
  /*! This class just provides a grouping of keys and values into a struct for
      human readable archives. For example, XML archives will use this wrapper
      to write maps like so:

      @code{.xml}
      <mymap>
        <item0>
          <key>MyFirstKey</key>
          <value>MyFirstValue</value>
        </item0>
        <item1>
          <key>MySecondKey</key>
          <value>MySecondValue</value>
        </item1>
      </mymap>
      @endcode

      \sa make_map_item
      @internal */
  template <class Key, class Value>
  struct MapItem
  {
    using KeyType = typename std::conditional<
      std::is_lvalue_reference<Key>::value,
      Key,
      typename std::decay<Key>::type>::type;

    using ValueType = typename std::conditional<
      std::is_lvalue_reference<Value>::value,
      Value,
      typename std::decay<Value>::type>::type;

    //! Construct a MapItem from a key and a value
    /*! @internal */
    MapItem( Key && key_, Value && value_ ) : key(key_), value(value_) {}

    KeyType key;
    ValueType value;

    //! Serialize the MapItem with the NVPs "key" and "value"
    template <class Archive> inline
    void CEREAL_SERIALIZE_FUNCTION_NAME(Archive & archive)
    {
      archive( make_nvp<Archive>("key",   key),
               make_nvp<Archive>("value", value) );
    }
  };

  //! Create a MapItem so that human readable archives will group keys and values together
  /*! @internal
      @relates MapItem */
  template <class KeyType, class ValueType> inline
  MapItem<KeyType, ValueType> make_map_item(KeyType && key, ValueType && value)
  {
    return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
  }

  namespace detail
  {
    // ######################################################################
    //! Holds all registered version information
    struct Versions
    {
      std::unordered_map<std::size_t, std::uint32_t> mapping;
    }; // struct Versions

    //! Version information class
    /*! This is the base case for classes that have not been explicitly
        registered */
    template <class T> struct Version
    {
      static const std::uint32_t version = 0;
      // we don't need to explicitly register these types since they
      // always get a version number of 0
    };

    #ifdef CEREAL_FUTURE_EXPERIMENTAL
    // ######################################################################
    //! A class that can store any type
    /*! This is inspired by boost::any and is intended to be a very light-weight
        replacement for internal use only.

        This class is only here as a candidate for issue #46 (see github) and
        should be considered unsupported until a future version of cereal.
        */
    class Any
    {
      private:
        //! Convenience alias for decay
        template <class T>
        using ST = typename std::decay<T>::type;

        struct Base
        {
          virtual ~Base() {}
          virtual std::unique_ptr<Base> clone() const = 0;
        };

        template <class T>
        struct Derived : Base
        {
          template <class U>
          Derived( U && data ) : value( std::forward<U>( data ) ) {}

          std::unique_ptr<Base> clone() const
          {
            return std::unique_ptr<Base>( new Derived<T>( value ) );
          }

          T value;
        };

      public:
        //! Construct from any type
        template <class T> inline
        Any( T && data ) :
          itsPtr( new Derived<ST<T>>( std::forward<T>( data ) ) )
        { }

        //! Convert to any type, if possible
        /*! Attempts to perform the conversion if possible,
            otherwise throws an exception.

            @throw Exception if conversion is not possible (see get() for more info)
            @tparam The requested type to convert to */
        template <class T> inline
        operator T()
        {
          return get<ST<T>>();
        }

        Any() : itsPtr() {}
        Any( Any & other ) : itsPtr( other.clone() ) {}
        Any( Any const & other ) : itsPtr( other.clone() ) {}
        Any( Any && other ) : itsPtr( std::move( other.itsPtr ) ) {}

        Any & operator=( Any const & other )
        {
          if( itsPtr == other.itsPtr ) return *this;

          auto cloned = other.clone();
          itsPtr = std::move( cloned );

          return *this;
        }

        Any & operator=( Any && other )
        {
          if( itsPtr == other.itsPtr ) return *this;

          itsPtr = std::move( other.itsPtr );

          return *this;
        }

      protected:
        //! Get the contained type as type T
        /*! @tparam T The requested type to convert to
            @return The type converted to T
            @throw Exception if conversion is impossible */
        template <class T>
        ST<T> & get()
        {
          auto * derived = dynamic_cast<Derived<ST<T>> *>( itsPtr.get() );

          if( !derived )
            throw ::cereal::Exception( "Invalid conversion requested on ASDFA" );

          return derived->value;
        }

        //! Clones the held data if it exists
        std::unique_ptr<Base> clone() const
        {
          if( itsPtr ) return itsPtr->clone();
          else return {};
        }

      private:
        std::unique_ptr<Base> itsPtr;
    }; // struct Any
    #endif // CEREAL_FUTURE_EXPERIMENTAL
  } // namespace detail
} // namespace cereal

#endif // CEREAL_DETAILS_HELPERS_HPP_
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qv8profilerservice_p.h"
#include "qqmldebugservice_p_p.h"
#include <private/qv8profiler_p.h>

#include <QtCore/QHash>
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>

QT_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(QV8ProfilerService, v8ProfilerInstance)

#if 0
// ### FIXME: v4
class DebugServiceOutputStream : public v8::OutputStream
{
public:
    DebugServiceOutputStream()
        : v8::OutputStream() {}
    void EndOfStream() {}
    WriteResult WriteAsciiChunk(char *rawData, int size)
    {
        QByteArray data;
        QQmlDebugStream ds(&data, QIODevice::WriteOnly);
        ds << QV8ProfilerService::V8SnapshotChunk << QByteArray(rawData, size);
        messages.append(data);
        return kContinue;
    }
    QList<QByteArray> messages;
};
#endif

// convert to a QByteArray that can be sent to the debug client
QByteArray QV8ProfilerData::toByteArray() const
{
    QByteArray data;
    //### using QDataStream is relatively expensive
    QQmlDebugStream ds(&data, QIODevice::WriteOnly);
    ds << messageType << filename << functionname << lineNumber << totalTime << selfTime << treeLevel;

    return data;
}

class QV8ProfilerServicePrivate : public QQmlDebugServicePrivate
{
    Q_DECLARE_PUBLIC(QV8ProfilerService)

public:
    QV8ProfilerServicePrivate()
        :initialized(false)
    {
    }

    // ### FIXME: v4
//    void takeSnapshot(v8::HeapSnapshot::Type);
//    void printProfileTree(const v8::CpuProfileNode *node, int level = 0);
//    void sendMessages();

    QList<QV8ProfilerData> m_data;

    bool initialized;
    QMutex initializeMutex;
    QWaitCondition initializeCondition;
    QList<QString> m_ongoing;
};

QV8ProfilerService::QV8ProfilerService(QObject *parent)
    : QQmlDebugService(*(new QV8ProfilerServicePrivate()), QStringLiteral("V8Profiler"), 1, parent)
{
    Q_D(QV8ProfilerService);

    QMutexLocker lock(&d->initializeMutex);

    if (registerService() == Enabled
            && QQmlDebugService::blockingMode()) {
        // let's wait for first message ...
        d->initializeCondition.wait(&d->initializeMutex);
    }
}

QV8ProfilerService::~QV8ProfilerService()
{
}

QV8ProfilerService *QV8ProfilerService::instance()
{
    return v8ProfilerInstance();
}

void QV8ProfilerService::initialize()
{
    // just make sure that the service is properly registered
    v8ProfilerInstance();
}

void QV8ProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
{
    Q_D(QV8ProfilerService);

    if (state() == newState)
        return;

    if (state() == Enabled) {
        foreach (const QString &title, d->m_ongoing) {
            QMetaObject::invokeMethod(this, "stopProfiling", Qt::BlockingQueuedConnection,
                                      Q_ARG(QString, title));
        }
        QMetaObject::invokeMethod(this, "sendProfilingData", Qt::BlockingQueuedConnection);
    } else {
        // wake up constructor in blocking mode
        // (we might got disabled before first message arrived)
        d->initializeCondition.wakeAll();
    }
}

void QV8ProfilerService::messageReceived(const QByteArray &message)
{
    Q_D(QV8ProfilerService);

    QQmlDebugStream ds(message);
    QByteArray command;
    QByteArray option;
    QByteArray title;
    ds >> command >> option;

    QMutexLocker lock(&d->initializeMutex);

    if (command == "V8PROFILER") {
        ds >>  title;
        QString titleStr = QString::fromUtf8(title);
        if (option == "start") {
            QMetaObject::invokeMethod(this, "startProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
        } else if (option == "stop" && d->initialized) {
            QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
            QMetaObject::invokeMethod(this, "sendProfilingData", Qt::QueuedConnection);
        }
        d->initialized = true;
    }

    if (command == "V8SNAPSHOT") {
        if (option == "full")
            QMetaObject::invokeMethod(this, "takeSnapshot", Qt::QueuedConnection);
        else if (option == "delete") {
            QMetaObject::invokeMethod(this, "deleteSnapshots", Qt::QueuedConnection);
        }
    }

    // wake up constructor in blocking mode
    d->initializeCondition.wakeAll();

    QQmlDebugService::messageReceived(message);
}

void QV8ProfilerService::startProfiling(const QString &title)
{
    Q_D(QV8ProfilerService);
    // Start Profiling

    if (d->m_ongoing.contains(title))
        return;

//    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
    // ### FIXME: v4
//    v8::CpuProfiler::StartProfiling(v8title);

    d->m_ongoing.append(title);

    // indicate profiling started
    QByteArray data;
    QQmlDebugStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8Started;

    sendMessage(data);
}

void QV8ProfilerService::stopProfiling(const QString &title)
{
    Q_D(QV8ProfilerService);
    // Stop profiling

    if (!d->m_ongoing.contains(title))
        return;
    d->m_ongoing.removeOne(title);

#if 0
    // ### FIXME: v4
    v8::HandleScope handle_scope;
    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
    const v8::CpuProfile *cpuProfile = v8::CpuProfiler::StopProfiling(v8title);
    if (cpuProfile) {
        // can happen at start
        const v8::CpuProfileNode *rootNode = cpuProfile->GetTopDownRoot();
        d->printProfileTree(rootNode);
    } else {
        // indicate completion, even without data
        QByteArray data;
        QQmlDebugStream ds(&data, QIODevice::WriteOnly);
        ds << (int)QV8ProfilerService::V8Complete;

        sendMessage(data);
    }
#endif
}

void QV8ProfilerService::takeSnapshot()
{
    Q_D(QV8ProfilerService);
    // ### FIXME: v4
//    d->takeSnapshot(v8::HeapSnapshot::kFull);
}

void QV8ProfilerService::deleteSnapshots()
{
    // ### FIXME: v4
//    v8::HeapProfiler::DeleteAllSnapshots();
}

void QV8ProfilerService::sendProfilingData()
{
    Q_D(QV8ProfilerService);
    // Send messages to client
    // ### FIXME: v4
//    d->sendMessages();
}

#if 0
// ### FIXME: v4
void QV8ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node, int level)
{
    for (int index = 0 ; index < node->GetChildrenCount() ; index++) {
        const v8::CpuProfileNode* childNode = node->GetChild(index);
        QString scriptResourceName = QJSConverter::toString(childNode->GetScriptResourceName());
        if (scriptResourceName.length() > 0) {

            QV8ProfilerData rd = {(int)QV8ProfilerService::V8Entry, scriptResourceName,
                QJSConverter::toString(childNode->GetFunctionName()),
                childNode->GetLineNumber(), childNode->GetTotalTime(), childNode->GetSelfTime(), level};
            m_data.append(rd);

            // different nodes might have common children: fix at client side
            if (childNode->GetChildrenCount() > 0) {
                printProfileTree(childNode, level+1);
            }
        }
    }
}

void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType)
{
    Q_Q(QV8ProfilerService);

    v8::HandleScope scope;
    v8::Handle<v8::String> title = v8::String::New("");

    DebugServiceOutputStream outputStream;
    const v8::HeapSnapshot *snapshot = v8::HeapProfiler::TakeSnapshot(title, snapshotType);
    snapshot->Serialize(&outputStream, v8::HeapSnapshot::kJSON);
    QList<QByteArray> messages = outputStream.messages;

    //indicate completion
    QByteArray data;
    QQmlDebugStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8SnapshotComplete;
    messages.append(data);

    q->sendMessages(messages);
}

void QV8ProfilerServicePrivate::sendMessages()
{
    Q_Q(QV8ProfilerService);

    QList<QByteArray> messages;
    for (int i = 0; i < m_data.count(); ++i)
        messages.append(m_data.at(i).toByteArray());
    m_data.clear();

    //indicate completion
    QByteArray data;
    QQmlDebugStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8Complete;
    messages.append(data);

    q->sendMessages(messages);
}
#endif

QT_END_NAMESPACE
<commit_msg>Make sure v8 service sends a finished signal<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQml module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qv8profilerservice_p.h"
#include "qqmldebugservice_p_p.h"
#include <private/qv8profiler_p.h>

#include <QtCore/QHash>
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>

QT_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(QV8ProfilerService, v8ProfilerInstance)

#if 0
// ### FIXME: v4
class DebugServiceOutputStream : public v8::OutputStream
{
public:
    DebugServiceOutputStream()
        : v8::OutputStream() {}
    void EndOfStream() {}
    WriteResult WriteAsciiChunk(char *rawData, int size)
    {
        QByteArray data;
        QQmlDebugStream ds(&data, QIODevice::WriteOnly);
        ds << QV8ProfilerService::V8SnapshotChunk << QByteArray(rawData, size);
        messages.append(data);
        return kContinue;
    }
    QList<QByteArray> messages;
};
#endif

// convert to a QByteArray that can be sent to the debug client
QByteArray QV8ProfilerData::toByteArray() const
{
    QByteArray data;
    //### using QDataStream is relatively expensive
    QQmlDebugStream ds(&data, QIODevice::WriteOnly);
    ds << messageType << filename << functionname << lineNumber << totalTime << selfTime << treeLevel;

    return data;
}

class QV8ProfilerServicePrivate : public QQmlDebugServicePrivate
{
    Q_DECLARE_PUBLIC(QV8ProfilerService)

public:
    QV8ProfilerServicePrivate()
        :initialized(false)
    {
    }

    // ### FIXME: v4
//    void takeSnapshot(v8::HeapSnapshot::Type);
//    void printProfileTree(const v8::CpuProfileNode *node, int level = 0);
//    void sendMessages();

    QList<QV8ProfilerData> m_data;

    bool initialized;
    QMutex initializeMutex;
    QWaitCondition initializeCondition;
    QList<QString> m_ongoing;
};

QV8ProfilerService::QV8ProfilerService(QObject *parent)
    : QQmlDebugService(*(new QV8ProfilerServicePrivate()), QStringLiteral("V8Profiler"), 1, parent)
{
    Q_D(QV8ProfilerService);

    QMutexLocker lock(&d->initializeMutex);

    if (registerService() == Enabled
            && QQmlDebugService::blockingMode()) {
        // let's wait for first message ...
        d->initializeCondition.wait(&d->initializeMutex);
    }
}

QV8ProfilerService::~QV8ProfilerService()
{
}

QV8ProfilerService *QV8ProfilerService::instance()
{
    return v8ProfilerInstance();
}

void QV8ProfilerService::initialize()
{
    // just make sure that the service is properly registered
    v8ProfilerInstance();
}

void QV8ProfilerService::stateAboutToBeChanged(QQmlDebugService::State newState)
{
    Q_D(QV8ProfilerService);

    if (state() == newState)
        return;

    if (state() == Enabled) {
        foreach (const QString &title, d->m_ongoing) {
            QMetaObject::invokeMethod(this, "stopProfiling", Qt::BlockingQueuedConnection,
                                      Q_ARG(QString, title));
        }
        QMetaObject::invokeMethod(this, "sendProfilingData", Qt::BlockingQueuedConnection);
    } else {
        // wake up constructor in blocking mode
        // (we might got disabled before first message arrived)
        d->initializeCondition.wakeAll();
    }
}

void QV8ProfilerService::messageReceived(const QByteArray &message)
{
    Q_D(QV8ProfilerService);

    QQmlDebugStream ds(message);
    QByteArray command;
    QByteArray option;
    QByteArray title;
    ds >> command >> option;

    QMutexLocker lock(&d->initializeMutex);

    if (command == "V8PROFILER") {
        ds >>  title;
        QString titleStr = QString::fromUtf8(title);
        if (option == "start") {
            QMetaObject::invokeMethod(this, "startProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
        } else if (option == "stop" && d->initialized) {
            QMetaObject::invokeMethod(this, "stopProfiling", Qt::QueuedConnection, Q_ARG(QString, titleStr));
            QMetaObject::invokeMethod(this, "sendProfilingData", Qt::QueuedConnection);
        }
        d->initialized = true;
    }

    if (command == "V8SNAPSHOT") {
        if (option == "full")
            QMetaObject::invokeMethod(this, "takeSnapshot", Qt::QueuedConnection);
        else if (option == "delete") {
            QMetaObject::invokeMethod(this, "deleteSnapshots", Qt::QueuedConnection);
        }
    }

    // wake up constructor in blocking mode
    d->initializeCondition.wakeAll();

    QQmlDebugService::messageReceived(message);
}

void QV8ProfilerService::startProfiling(const QString &title)
{
    Q_D(QV8ProfilerService);
    // Start Profiling

    if (d->m_ongoing.contains(title))
        return;

//    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
    // ### FIXME: v4
//    v8::CpuProfiler::StartProfiling(v8title);

    d->m_ongoing.append(title);

    // indicate profiling started
    QByteArray data;
    QQmlDebugStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8Started;

    sendMessage(data);
}

void QV8ProfilerService::stopProfiling(const QString &title)
{
    Q_D(QV8ProfilerService);
    // Stop profiling

    if (!d->m_ongoing.contains(title))
        return;
    d->m_ongoing.removeOne(title);

#if 0
    // ### FIXME: v4
    v8::HandleScope handle_scope;
    v8::Handle<v8::String> v8title = v8::String::New(reinterpret_cast<const uint16_t*>(title.data()), title.size());
    const v8::CpuProfile *cpuProfile = v8::CpuProfiler::StopProfiling(v8title);
    if (cpuProfile) {
        // can happen at start
        const v8::CpuProfileNode *rootNode = cpuProfile->GetTopDownRoot();
        d->printProfileTree(rootNode);
    } else {
#endif
        // indicate completion, even without data
        QByteArray data;
        QQmlDebugStream ds(&data, QIODevice::WriteOnly);
        ds << (int)QV8ProfilerService::V8Complete;

        sendMessage(data);
#if 0
    }
#endif
}

void QV8ProfilerService::takeSnapshot()
{
    Q_D(QV8ProfilerService);
    // ### FIXME: v4
//    d->takeSnapshot(v8::HeapSnapshot::kFull);
}

void QV8ProfilerService::deleteSnapshots()
{
    // ### FIXME: v4
//    v8::HeapProfiler::DeleteAllSnapshots();
}

void QV8ProfilerService::sendProfilingData()
{
    Q_D(QV8ProfilerService);
    // Send messages to client
    // ### FIXME: v4
//    d->sendMessages();
}

#if 0
// ### FIXME: v4
void QV8ProfilerServicePrivate::printProfileTree(const v8::CpuProfileNode *node, int level)
{
    for (int index = 0 ; index < node->GetChildrenCount() ; index++) {
        const v8::CpuProfileNode* childNode = node->GetChild(index);
        QString scriptResourceName = QJSConverter::toString(childNode->GetScriptResourceName());
        if (scriptResourceName.length() > 0) {

            QV8ProfilerData rd = {(int)QV8ProfilerService::V8Entry, scriptResourceName,
                QJSConverter::toString(childNode->GetFunctionName()),
                childNode->GetLineNumber(), childNode->GetTotalTime(), childNode->GetSelfTime(), level};
            m_data.append(rd);

            // different nodes might have common children: fix at client side
            if (childNode->GetChildrenCount() > 0) {
                printProfileTree(childNode, level+1);
            }
        }
    }
}

void QV8ProfilerServicePrivate::takeSnapshot(v8::HeapSnapshot::Type snapshotType)
{
    Q_Q(QV8ProfilerService);

    v8::HandleScope scope;
    v8::Handle<v8::String> title = v8::String::New("");

    DebugServiceOutputStream outputStream;
    const v8::HeapSnapshot *snapshot = v8::HeapProfiler::TakeSnapshot(title, snapshotType);
    snapshot->Serialize(&outputStream, v8::HeapSnapshot::kJSON);
    QList<QByteArray> messages = outputStream.messages;

    //indicate completion
    QByteArray data;
    QQmlDebugStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8SnapshotComplete;
    messages.append(data);

    q->sendMessages(messages);
}

void QV8ProfilerServicePrivate::sendMessages()
{
    Q_Q(QV8ProfilerService);

    QList<QByteArray> messages;
    for (int i = 0; i < m_data.count(); ++i)
        messages.append(m_data.at(i).toByteArray());
    m_data.clear();

    //indicate completion
    QByteArray data;
    QQmlDebugStream ds(&data, QIODevice::WriteOnly);
    ds << (int)QV8ProfilerService::V8Complete;
    messages.append(data);

    q->sendMessages(messages);
}
#endif

QT_END_NAMESPACE
<|endoftext|>


<commit_before>//TODO: deprecated, remove whole file.

/**
 * @file Exc.hpp
 * @author Ivan Gagis <igagis@gmail.com>
 * @brief Basic Exception class.
 */

#pragma once

#include <string>
#include <exception>

#include "config.hpp"

namespace utki{

/**
 * @brief Basic exception class
 */
class Exc : public std::exception{
	std::string message;
public:
	/**
	 * @brief Constructor.
	 * @param message - human friendly error description.
	 */
	Exc(const std::string& message = std::string()) :
			message(message)
	{}

	virtual ~Exc()noexcept{}

	/**
	 * @brief Returns a pointer to exception message.
	 * @return a pointer to objects internal memory buffer holding
	 *         the exception message null-terminated string.
	 *         Note, that after the exception object is destroyed
	 *         the pointer returned by this method become invalid.
	 */
	const char *what()const noexcept override{
		return this->message.c_str();
	}
};

}//~namespace
<commit_msg>deprecated warning<commit_after>//TODO: deprecated, remove whole file.
#warning utki/Exc.hpp is deprecated, use utki/exception.hpp
/**
 * @file Exc.hpp
 * @author Ivan Gagis <igagis@gmail.com>
 * @brief Basic Exception class.
 */

#pragma once

#include <string>
#include <exception>

#include "config.hpp"

namespace utki{

/**
 * @brief Basic exception class
 */
class Exc : public std::exception{
	std::string message;
public:
	/**
	 * @brief Constructor.
	 * @param message - human friendly error description.
	 */
	Exc(const std::string& message = std::string()) :
			message(message)
	{}

	virtual ~Exc()noexcept{}

	/**
	 * @brief Returns a pointer to exception message.
	 * @return a pointer to objects internal memory buffer holding
	 *         the exception message null-terminated string.
	 *         Note, that after the exception object is destroyed
	 *         the pointer returned by this method become invalid.
	 */
	const char *what()const noexcept override{
		return this->message.c_str();
	}
};

}//~namespace
<|endoftext|>


<commit_before>#include "all.h"

void Noodle::push(int sample)
{
	assert(m_queue.size() <= m_max);
	m_queue.push(sample);
}

int Noodle::pop(void)
{
	int sample = m_queue.front();
	m_queue.pop();
	return sample;

}

int Noodle::peek(size_t where)
{
#warning TODO
	// TODO
}
<commit_msg>fix whitespace<commit_after>#include "all.h"

void Noodle::push(int sample)
{
	assert(m_queue.size() <= m_max);
	m_queue.push(sample);
}

int Noodle::pop(void)
{
	int sample = m_queue.front();
	m_queue.pop();
	return sample;
}

int Noodle::peek(size_t where)
{
#warning TODO
	// TODO
}
<|endoftext|>