<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkSymmetricSecondRankTensorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>

#include "itkSymmetricSecondRankTensor.h"
#include "itkImage.h"
#include "itkImageRegionIterator.h"

int itkSymmetricSecondRankTensorTest(int, char* [] )
{
  int i, j;

  // Test it all

  float val[6] = {1.8, 0.2, 0.5, 3.4, 2.0, 1.2};

  typedef itk::SymmetricSecondRankTensor<float,3>         Float3DTensorType;
  typedef itk::SymmetricSecondRankTensor<unsigned char,3> Uchar3DTensorType;

  Float3DTensorType pixel(val);

  unsigned char pixelInit0[6] = {255, 255, 255,128,34,17};
  unsigned char pixelInit1[6] = {255, 255, 244,19,23,29};

  Uchar3DTensorType pixelArray[2];
  pixelArray[0] = pixelInit0;
  pixelArray[1] = pixelInit1;

  std::cout << "sizeof(pixel) = " << sizeof (pixel) << std::endl;
  if (sizeof(pixel) != 6 * sizeof(Float3DTensorType::ComponentType))
    {
    std::cerr << "ERROR: sizeof(pixel) == " << sizeof(pixel) << " but is should be " << 6 * sizeof(Float3DTensorType::ComponentType) << std::endl;
    return 1;
    }
  std::cout << "pixel.GetNumberOfComponents = " << pixel.GetNumberOfComponents() << std::endl;
  std::cout << "pixel.GetNthComponent()" << std::endl;
  for (i = 0; i < pixel.GetNumberOfComponents(); i++)
    {
    std::cout << "\tpixel[" << i << "] = " << pixel.GetNthComponent(i) << std::endl;
    }

  pixel(0,0) = 11.0;
  pixel(0,1) = 21.0;
  pixel(0,2) = 15.0;
  pixel(1,0) = 11.0;
  pixel(1,1) = 31.0;
  pixel(1,2) = 10.0;
  pixel(2,0) = 11.0; // these three last element will overwrite its symmetric counterparts
  pixel(2,1) = 41.0;
  pixel(2,2) = 14.0;

  std::cout << "testing the pixel(i,j) APID" << std::endl;
  for (i = 0; i < pixel.GetNumberOfComponents(); i++)
    {
    std::cout << "\tpixel[" << i << "] = " << pixel.GetNthComponent(i) << std::endl;
    }

  std::cout << "pixel[0] = 111; pixel[1] = 222; pixel[2] = 333;" << std::endl;
  std::cout << "pixel[3] = 444; pixel[4] = 555; pixel[5] = 666;" << std::endl;

  pixel[0] = 111; pixel[1] = 222; pixel[2] = 333;
  pixel[3] = 444; pixel[4] = 555; pixel[5] = 666;

  for (i = 0; i < pixel.GetNumberOfComponents(); i++)
    {
    std::cout << "\tpixel[" << i << "] = " << pixel.GetNthComponent(i) << std::endl;
    }

  std::cout << "std::cout << pixel << std::endl;" << std::endl;
  std::cout << "\t" << pixel << std::endl;

  for (j = 0; j < 2; j++)
    {
    std::cout << "pixelArray["<< j << "].GetNumberOfComponents = " << pixelArray[j].GetNumberOfComponents() << std::endl;
    std::cout << "pixelArray[" << j << "].GetNthComponent()" << std::endl;
    for (i = 0; i < pixelArray[j].GetNumberOfComponents(); i++)
      {
      std::cout << "\tpixelArray[" << j << "].GetNthComponent(" << i << ") = " << static_cast<int>(pixelArray[j].GetNthComponent(i)) << std::endl;
      }
    }

  std::cout << "Testing arithmetic methods" << std::endl;
  Float3DTensorType pa;
  Float3DTensorType pb;

  pa[0] = 1.25;
  pa[1] = 3.25;
  pa[2] = 5.25;
  pa[3] = 1.25;
  pa[4] = 3.25;
  pa[5] = 5.25;

  pb[0] = 1.55;
  pb[1] = 3.55;
  pb[2] = 5.55;
  pb[3] = 1.55;
  pb[4] = 3.55;
  pb[5] = 5.55;

  Float3DTensorType pc;

  pc = pa + pb;
  std::cout << "addition = " << pc << std::endl;

  pc = pa - pb;
  std::cout << "subtraction = " << pc << std::endl;

  pc += pb;
  std::cout << "in-place addition = " << pc << std::endl;

  pc -= pb;
  std::cout << "in-place subtraction = " << pc << std::endl;

  pc = pa * 3.2;
  std::cout << "product by scalar = " << pc << std::endl;

  /** Create an Image of tensors  */
  typedef Float3DTensorType   PixelType;
  typedef itk::Image< PixelType, 3 >           ImageType;

  ImageType::Pointer dti = ImageType::New();

  ImageType::SizeType  size;
  ImageType::IndexType start;
  ImageType::RegionType region;

  size[0] = 128;
  size[1] = 128;
  size[2] = 128;

  start[0] = 0;
  start[1] = 0;
  start[2] = 0;

  region.SetIndex( start );
  region.SetSize( size );

  dti->SetRegions( region );
  dti->Allocate();

  ImageType::SpacingType spacing;
  spacing[0] = 0.5;
  spacing[1] = 0.5;
  spacing[2] = 1.5;

  ImageType::PointType origin;
  origin[0] = 25.5;
  origin[1] = 25.5;
  origin[2] = 27.5;

  dti->SetOrigin( origin );
  dti->SetSpacing( spacing );

  PixelType tensor;

  tensor[0] = 1.2;
  tensor[1] = 2.2;
  tensor[2] = 3.2;
  tensor[3] = 4.2;
  tensor[4] = 5.2;
  tensor[5] = 6.2;

  dti->FillBuffer( tensor );

  typedef itk::ImageRegionIterator< ImageType > IteratorType;

  IteratorType it( dti, region );
  it.GoToBegin();

  while( !it.IsAtEnd() )
    {
    it.Set( tensor );
    ++it;
    }

  // Test Eigen values computation
  {
    typedef itk::SymmetricSecondRankTensor<double,3>         Double3DTensorType;

    Double3DTensorType tensor;

    Double3DTensorType::EigenValuesArrayType     eigenValues;
    Double3DTensorType::EigenVectorsMatrixType   eigenVectors;

    tensor.ComputeEigenAnalysis( eigenValues, eigenVectors );

    std::cout << "EigenValues = " << std::endl;
    std::cout << eigenValues << std::endl;

    std::cout << "EigenVectors = " << std::endl;
    std::cout << eigenVectors << std::endl;
  }

  return EXIT_SUCCESS;
}

<commit_msg>ENH: Added trivial test for eigen analysis: a diagonal tensor.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkSymmetricSecondRankTensorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>

#include "itkSymmetricSecondRankTensor.h"
#include "itkImage.h"
#include "itkImageRegionIterator.h"

int itkSymmetricSecondRankTensorTest(int, char* [] )
{
  int i, j;

  // Test it all

  float val[6] = {1.8, 0.2, 0.5, 3.4, 2.0, 1.2};

  typedef itk::SymmetricSecondRankTensor<float,3>         Float3DTensorType;
  typedef itk::SymmetricSecondRankTensor<unsigned char,3> Uchar3DTensorType;

  Float3DTensorType pixel(val);

  unsigned char pixelInit0[6] = {255, 255, 255,128,34,17};
  unsigned char pixelInit1[6] = {255, 255, 244,19,23,29};

  Uchar3DTensorType pixelArray[2];
  pixelArray[0] = pixelInit0;
  pixelArray[1] = pixelInit1;

  std::cout << "sizeof(pixel) = " << sizeof (pixel) << std::endl;
  if (sizeof(pixel) != 6 * sizeof(Float3DTensorType::ComponentType))
    {
    std::cerr << "ERROR: sizeof(pixel) == " << sizeof(pixel) << " but is should be " << 6 * sizeof(Float3DTensorType::ComponentType) << std::endl;
    return 1;
    }
  std::cout << "pixel.GetNumberOfComponents = " << pixel.GetNumberOfComponents() << std::endl;
  std::cout << "pixel.GetNthComponent()" << std::endl;
  for (i = 0; i < pixel.GetNumberOfComponents(); i++)
    {
    std::cout << "\tpixel[" << i << "] = " << pixel.GetNthComponent(i) << std::endl;
    }

  pixel(0,0) = 11.0;
  pixel(0,1) = 21.0;
  pixel(0,2) = 15.0;
  pixel(1,0) = 11.0;
  pixel(1,1) = 31.0;
  pixel(1,2) = 10.0;
  pixel(2,0) = 11.0; // these three last element will overwrite its symmetric counterparts
  pixel(2,1) = 41.0;
  pixel(2,2) = 14.0;

  std::cout << "testing the pixel(i,j) APID" << std::endl;
  for (i = 0; i < pixel.GetNumberOfComponents(); i++)
    {
    std::cout << "\tpixel[" << i << "] = " << pixel.GetNthComponent(i) << std::endl;
    }

  std::cout << "pixel[0] = 111; pixel[1] = 222; pixel[2] = 333;" << std::endl;
  std::cout << "pixel[3] = 444; pixel[4] = 555; pixel[5] = 666;" << std::endl;

  pixel[0] = 111; pixel[1] = 222; pixel[2] = 333;
  pixel[3] = 444; pixel[4] = 555; pixel[5] = 666;

  for (i = 0; i < pixel.GetNumberOfComponents(); i++)
    {
    std::cout << "\tpixel[" << i << "] = " << pixel.GetNthComponent(i) << std::endl;
    }

  std::cout << "std::cout << pixel << std::endl;" << std::endl;
  std::cout << "\t" << pixel << std::endl;

  for (j = 0; j < 2; j++)
    {
    std::cout << "pixelArray["<< j << "].GetNumberOfComponents = " << pixelArray[j].GetNumberOfComponents() << std::endl;
    std::cout << "pixelArray[" << j << "].GetNthComponent()" << std::endl;
    for (i = 0; i < pixelArray[j].GetNumberOfComponents(); i++)
      {
      std::cout << "\tpixelArray[" << j << "].GetNthComponent(" << i << ") = " << static_cast<int>(pixelArray[j].GetNthComponent(i)) << std::endl;
      }
    }

  std::cout << "Testing arithmetic methods" << std::endl;
  Float3DTensorType pa;
  Float3DTensorType pb;

  pa[0] = 1.25;
  pa[1] = 3.25;
  pa[2] = 5.25;
  pa[3] = 1.25;
  pa[4] = 3.25;
  pa[5] = 5.25;

  pb[0] = 1.55;
  pb[1] = 3.55;
  pb[2] = 5.55;
  pb[3] = 1.55;
  pb[4] = 3.55;
  pb[5] = 5.55;

  Float3DTensorType pc;

  pc = pa + pb;
  std::cout << "addition = " << pc << std::endl;

  pc = pa - pb;
  std::cout << "subtraction = " << pc << std::endl;

  pc += pb;
  std::cout << "in-place addition = " << pc << std::endl;

  pc -= pb;
  std::cout << "in-place subtraction = " << pc << std::endl;

  pc = pa * 3.2;
  std::cout << "product by scalar = " << pc << std::endl;

  /** Create an Image of tensors  */
  typedef Float3DTensorType   PixelType;
  typedef itk::Image< PixelType, 3 >           ImageType;

  ImageType::Pointer dti = ImageType::New();

  ImageType::SizeType  size;
  ImageType::IndexType start;
  ImageType::RegionType region;

  size[0] = 128;
  size[1] = 128;
  size[2] = 128;

  start[0] = 0;
  start[1] = 0;
  start[2] = 0;

  region.SetIndex( start );
  region.SetSize( size );

  dti->SetRegions( region );
  dti->Allocate();

  ImageType::SpacingType spacing;
  spacing[0] = 0.5;
  spacing[1] = 0.5;
  spacing[2] = 1.5;

  ImageType::PointType origin;
  origin[0] = 25.5;
  origin[1] = 25.5;
  origin[2] = 27.5;

  dti->SetOrigin( origin );
  dti->SetSpacing( spacing );

  PixelType tensor;

  tensor[0] = 1.2;
  tensor[1] = 2.2;
  tensor[2] = 3.2;
  tensor[3] = 4.2;
  tensor[4] = 5.2;
  tensor[5] = 6.2;

  dti->FillBuffer( tensor );

  typedef itk::ImageRegionIterator< ImageType > IteratorType;

  IteratorType it( dti, region );
  it.GoToBegin();

  while( !it.IsAtEnd() )
    {
    it.Set( tensor );
    ++it;
    }

  // Test Eigen values computation
  {
    typedef itk::SymmetricSecondRankTensor<double,3>         Double3DTensorType;

    Double3DTensorType tensor;

    double v[3];
    v[0] = 19.0;
    v[1] = 23.0;
    v[2] = 29.0;

    tensor(0,0) = v[0];
    tensor(0,1) =  0.0;
    tensor(0,2) =  0.0;
    tensor(1,0) =  0.0; // overrides (0,1)
    tensor(1,1) = v[1];
    tensor(1,2) =  0.0;
    tensor(2,0) =  0.0; // overrides (0,2)
    tensor(2,1) =  0.0; // overrides (1,2)
    tensor(2,2) = v[2];

    std::cout << "SymmetricTensor = " << std::endl;
    std::cout << tensor << std::endl;

    Double3DTensorType::EigenValuesArrayType     eigenValues;
    Double3DTensorType::EigenVectorsMatrixType   eigenVectors;

    tensor.ComputeEigenAnalysis( eigenValues, eigenVectors );

    std::cout << "EigenValues = " << std::endl;
    std::cout << eigenValues << std::endl;

    std::cout << "EigenVectors = " << std::endl;
    std::cout << eigenVectors << std::endl;

    const double tolerance = 1e-8;

    for(unsigned int i=0; i<3; i++)
      {
      if( fabs( v[i] - eigenValues[i] ) > tolerance )
        {
        std::cerr << "Eigenvalue computation failed" << std::endl;
        return EXIT_FAILURE;
        }
      }
  }

  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include "blackmagicsdk_video_source.h"

namespace gg
{

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK()
    : IVideoSource()
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    // This constructor should never be called,
    // therefore setting I420 arbitrarily for the
    // buffer video frame here.
    , _buffer_video_frame(VideoFrame(I420))
    , _running(false)
{
    // nop
}

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK(size_t deck_link_index,
                                                   ColourSpace colour)
    : IVideoSource(colour)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    , _buffer_video_frame(VideoFrame(colour, false)) // TODO manage data?
    , _deck_link(nullptr)
    , _deck_link_input(nullptr)
    , _running(false)
{
    switch(_colour)
    {
    case BGRA:
        break;
    case I420:
    default:
        release_deck_link();
        throw VideoSourceError(
            "BlackmagicSDK video source supports only BGRA"
        );
    }

    // Get an iterator through the available DeckLink ports
    IDeckLinkIterator * deck_link_iterator = CreateDeckLinkIteratorInstance();
    if (deck_link_iterator == nullptr)
    {
        release_deck_link();
        throw VideoSourceError("DeckLink drivers do not appear to be installed");
    }

    HRESULT res;

    // Get the desired DeckLink index (port)
    int idx = deck_link_index;
    while ((res = deck_link_iterator->Next(&_deck_link)) == S_OK)
    {
        if (idx == 0)
            break;
        --idx;

        _deck_link->Release();
    }
    if (deck_link_iterator != nullptr)
        deck_link_iterator->Release();
    // No glory: release everything and throw exception
    if (res != S_OK or _deck_link == nullptr)
    {
        release_deck_link();
        throw VideoSourceError(
            std::string("Could not get DeckLink device ").append(std::to_string(deck_link_index))
        );
    }

    // Get the input interface of connected DeckLink port
    res = _deck_link->QueryInterface(IID_IDeckLinkInput, reinterpret_cast<void **>(&_deck_link_input));
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not connect to any Blackmagic DeckLink device");
    }

    // Set this object (IDeckLinkInputCallback instance) as callback
    res = _deck_link_input->SetCallback(this);
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not set the callback of Blackmagic DeckLink device");
    }

    // Enable video input
    res = _deck_link_input->EnableVideoInput(
        bmdModeHD1080p6000, bmdFormat8BitBGRA,
        bmdVideoInputFlagDefault | bmdVideoInputEnableFormatDetection
    );
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not enable video input of Blackmagic DeckLink device");
    }

    // Disable audio input
    res = _deck_link_input->DisableAudioInput();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not disable audio input of Blackmagic DeckLink device");
    }
}

VideoSourceBlackmagicSDK::~VideoSourceBlackmagicSDK()
{
    // Release DeckLink members
    release_deck_link();

    // Release allocated memory
    free(_video_buffer);
    // TODO
}

bool VideoSourceBlackmagicSDK::get_frame_dimensions(int & width, int & height)
{
    // TODO
}

bool VideoSourceBlackmagicSDK::get_frame(VideoFrame & frame)
{
    // TODO
    return false;
}

double VideoSourceBlackmagicSDK::get_frame_rate()
{
    // TODO
    return 0;
}

void VideoSourceBlackmagicSDK::set_sub_frame(int x, int y, int width, int height)
{
    // TODO
}

void VideoSourceBlackmagicSDK::get_full_frame()
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::QueryInterface(REFIID iid, LPVOID * ppv)
{
    // TODO
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::AddRef(void)
{
    // TODO
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::Release(void)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFormatChanged(
    BMDVideoInputFormatChangedEvents events,
    IDeckLinkDisplayMode * display_mode,
    BMDDetectedVideoInputFormatFlags format_flags
)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFrameArrived(
    IDeckLinkVideoInputFrame * video_frame,
    IDeckLinkAudioInputPacket * audio_packet
)
{
    // TODO
}

void VideoSourceBlackmagicSDK::release_deck_link() noexcept
{
    this->Release();

    if (_deck_link_input != nullptr)
    {
        _deck_link_input->Release();
        _deck_link_input = nullptr;
    }

    if (_deck_link != nullptr)
        _deck_link->Release();
}

}
<commit_msg>Issue #5: BlackmagicSDK video source constructor now starts streaming at the end, destructor stops it<commit_after>#include "blackmagicsdk_video_source.h"

namespace gg
{

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK()
    : IVideoSource()
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    // This constructor should never be called,
    // therefore setting I420 arbitrarily for the
    // buffer video frame here.
    , _buffer_video_frame(VideoFrame(I420))
    , _running(false)
{
    // nop
}

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK(size_t deck_link_index,
                                                   ColourSpace colour)
    : IVideoSource(colour)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    , _buffer_video_frame(VideoFrame(colour, false)) // TODO manage data?
    , _deck_link(nullptr)
    , _deck_link_input(nullptr)
    , _running(false)
{
    switch(_colour)
    {
    case BGRA:
        break;
    case I420:
    default:
        release_deck_link();
        throw VideoSourceError(
            "BlackmagicSDK video source supports only BGRA"
        );
    }

    // Get an iterator through the available DeckLink ports
    IDeckLinkIterator * deck_link_iterator = CreateDeckLinkIteratorInstance();
    if (deck_link_iterator == nullptr)
    {
        release_deck_link();
        throw VideoSourceError("DeckLink drivers do not appear to be installed");
    }

    HRESULT res;

    // Get the desired DeckLink index (port)
    int idx = deck_link_index;
    while ((res = deck_link_iterator->Next(&_deck_link)) == S_OK)
    {
        if (idx == 0)
            break;
        --idx;

        _deck_link->Release();
    }
    if (deck_link_iterator != nullptr)
        deck_link_iterator->Release();
    // No glory: release everything and throw exception
    if (res != S_OK or _deck_link == nullptr)
    {
        release_deck_link();
        throw VideoSourceError(
            std::string("Could not get DeckLink device ").append(std::to_string(deck_link_index))
        );
    }

    // Get the input interface of connected DeckLink port
    res = _deck_link->QueryInterface(IID_IDeckLinkInput, reinterpret_cast<void **>(&_deck_link_input));
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not connect to any Blackmagic DeckLink device");
    }

    // Set this object (IDeckLinkInputCallback instance) as callback
    res = _deck_link_input->SetCallback(this);
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not set the callback of Blackmagic DeckLink device");
    }

    // Enable video input
    res = _deck_link_input->EnableVideoInput(
        bmdModeHD1080p6000, bmdFormat8BitBGRA,
        bmdVideoInputFlagDefault | bmdVideoInputEnableFormatDetection
    );
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not enable video input of Blackmagic DeckLink device");
    }

    // Disable audio input
    res = _deck_link_input->DisableAudioInput();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not disable audio input of Blackmagic DeckLink device");
    }

    // Start streaming
    _running = true;
    res = _deck_link_input->StartStreams();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        _running = false;
        release_deck_link();
        throw VideoSourceError("Could not start streaming from the Blackmagic DeckLink device");
    }
}

VideoSourceBlackmagicSDK::~VideoSourceBlackmagicSDK()
{
    // Make sure streamer thread not trying to access buffer
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);
    _running = false;

    // Stop streaming and disable enabled inputs
    _deck_link_input->StopStreams();
    _deck_link_input->DisableVideoInput();

    // Release DeckLink members
    release_deck_link();

    // Release allocated memory
    free(_video_buffer);
}

bool VideoSourceBlackmagicSDK::get_frame_dimensions(int & width, int & height)
{
    // TODO
}

bool VideoSourceBlackmagicSDK::get_frame(VideoFrame & frame)
{
    // TODO
    return false;
}

double VideoSourceBlackmagicSDK::get_frame_rate()
{
    // TODO
    return 0;
}

void VideoSourceBlackmagicSDK::set_sub_frame(int x, int y, int width, int height)
{
    // TODO
}

void VideoSourceBlackmagicSDK::get_full_frame()
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::QueryInterface(REFIID iid, LPVOID * ppv)
{
    // TODO
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::AddRef(void)
{
    // TODO
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::Release(void)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFormatChanged(
    BMDVideoInputFormatChangedEvents events,
    IDeckLinkDisplayMode * display_mode,
    BMDDetectedVideoInputFormatFlags format_flags
)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFrameArrived(
    IDeckLinkVideoInputFrame * video_frame,
    IDeckLinkAudioInputPacket * audio_packet
)
{
    // TODO
}

void VideoSourceBlackmagicSDK::release_deck_link() noexcept
{
    this->Release();

    if (_deck_link_input != nullptr)
    {
        _deck_link_input->Release();
        _deck_link_input = nullptr;
    }

    if (_deck_link != nullptr)
        _deck_link->Release();
}

}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

// iostream is used for general output
#include <iostream>
#include <stdlib.h>

#include "otbMacro.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMapProjections.h"
#include "itkComplexToModulusImageFilter.h"
#include "otbUnaryImageFunctorWithVectorImageFilter.h"
#include "otbOrthoRectificationFilter.h"
#include "otbMapProjections.h"

int otbOrthoRectificationFilter(int argc, char* argv[])
{
  if (argc != 12)
    {
    std::cout << argv[0] <<
    " <input filename> <output filename> <origin easting> <origin northing> <x size> <y size> <x spacing> <y spacing> <UTM zone> <UTM hemisphere>"
              << std::endl;

    return EXIT_FAILURE;
    }

  typedef otb::VectorImage<double, 2>                                               VectorImageType;
  typedef otb::ImageFileReader<VectorImageType>                                     ReaderType;
  typedef otb::ImageFileWriter<VectorImageType>                            WriterType;
  typedef otb::UtmInverseProjection                                                 UtmMapProjectionType;
  typedef otb::OrthoRectificationFilter<VectorImageType, VectorImageType, UtmMapProjectionType> OrthoRectifFilterType;

  //Allocate pointer
  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  OrthoRectifFilterType::Pointer orthoRectifFilter = OrthoRectifFilterType::New();
  UtmMapProjectionType::Pointer  utmMapProjection = UtmMapProjectionType::New();

  // Set parameters ...
  reader->SetFileName(argv[1]);
  writer->SetFileName(argv[2]);

  reader->GenerateOutputInformation();
  std::cout << reader->GetOutput() << std::endl;

  orthoRectifFilter->SetInput(reader->GetOutput());

  VectorImageType::IndexType start;
  start[0] = 0;
  start[1] = 0;
  orthoRectifFilter->SetOutputStartIndex(start);

  VectorImageType::SizeType size;
  size[0] = atoi(argv[5]);      // X size
  size[1] = atoi(argv[6]);            //Y size
  orthoRectifFilter->SetOutputSize(size);

  VectorImageType::SpacingType spacing;
  spacing[0] = atof(argv[7]);
  spacing[1] = atof(argv[8]);
  orthoRectifFilter->SetOutputSpacing(spacing);

  VectorImageType::PointType origin;
  origin[0] = strtod(argv[3], NULL);         //Origin easting
  origin[1] = strtod(argv[4], NULL);         //Origin northing
  orthoRectifFilter->SetOutputOrigin(origin);

  utmMapProjection->SetZone(atoi(argv[9]));
  utmMapProjection->SetHemisphere(argv[10][0]);
  orthoRectifFilter->SetMapProjection(utmMapProjection);

  // Displacement Field spacing
  VectorImageType::SpacingType  gridSpacing;
  gridSpacing[0] = atof(argv[11]);
  gridSpacing[1] = -atof(argv[11]);
  orthoRectifFilter->SetDisplacementFieldSpacing(gridSpacing);

  VectorImageType::PixelType no_data(reader->GetOutput()->GetNumberOfComponentsPerPixel());
  no_data.Fill(0);
  orthoRectifFilter->SetEdgePaddingValue(no_data);

  writer->SetInput(orthoRectifFilter->GetOutput());
  writer->SetNumberOfDivisionsTiledStreaming(4);
  writer->Update();

  return EXIT_SUCCESS;
}

int otbOrthoRectificationComplexFilter(int argc, char* argv[])
{
  if (argc != 12)
    {
    std::cout << argv[0] <<
    " <input filename> <output filename> <origin easting> <origin northing> <x size> <y size> <x spacing> <y spacing> <UTM zone> <UTM hemisphere>"
              << std::endl;

    return EXIT_FAILURE;
    }

  typedef otb::VectorImage<std::complex<double>, 2>                                 ComplexVectorImageType;
  typedef otb::VectorImage<double, 2>                                               ModulusVectorImageType;
  typedef otb::UnaryImageFunctorWithVectorImageFilter<
                        ComplexVectorImageType,
                        ModulusVectorImageType,
                        itk::Functor::ComplexToModulus<
                          ComplexVectorImageType::InternalPixelType,
                          ModulusVectorImageType::InternalPixelType
                          >
                        >                                                           ComplexToModulusFilterType;
  typedef otb::ImageFileReader<ComplexVectorImageType>                              ReaderType;
  typedef otb::ImageFileWriter<ModulusVectorImageType>                     WriterType;
  typedef otb::UtmInverseProjection                                                 UtmMapProjectionType;
  typedef otb::OrthoRectificationFilter<ModulusVectorImageType, ModulusVectorImageType, UtmMapProjectionType> OrthoRectifFilterType;

  //Allocate pointer
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(argv[1]);
  reader->GenerateOutputInformation();
  std::cout << reader->GetOutput() << std::endl;

  ComplexToModulusFilterType::Pointer complexToModulus = ComplexToModulusFilterType::New();
  complexToModulus->SetInput(reader->GetOutput());

  UtmMapProjectionType::Pointer  utmMapProjection = UtmMapProjectionType::New();
  OrthoRectifFilterType::Pointer orthoRectifFilter = OrthoRectifFilterType::New();

  orthoRectifFilter->SetInput(complexToModulus->GetOutput());

  ComplexVectorImageType::IndexType start;
  start[0] = 0;
  start[1] = 0;
  orthoRectifFilter->SetOutputStartIndex(start);

  ComplexVectorImageType::SizeType size;
  size[0] = atoi(argv[5]);      // X size
  size[1] = atoi(argv[6]);            //Y size
  orthoRectifFilter->SetOutputSize(size);

  ComplexVectorImageType::SpacingType spacing;
  spacing[0] = atof(argv[7]);
  spacing[1] = atof(argv[8]);
  orthoRectifFilter->SetOutputSpacing(spacing);

  ComplexVectorImageType::PointType origin;
  origin[0] = strtod(argv[3], NULL);         //Origin easting
  origin[1] = strtod(argv[4], NULL);         //Origin northing
  orthoRectifFilter->SetOutputOrigin(origin);

  utmMapProjection->SetZone(atoi(argv[9]));
  utmMapProjection->SetHemisphere(argv[10][0]);
  orthoRectifFilter->SetMapProjection(utmMapProjection);

  // Displacement Field spacing
  ComplexVectorImageType::SpacingType  gridSpacing;
  gridSpacing[0] = atof(argv[11]);
  gridSpacing[1] = -atof(argv[11]);
  orthoRectifFilter->SetDisplacementFieldSpacing(gridSpacing);

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(argv[2]);
  writer->SetInput(orthoRectifFilter->GetOutput());
  writer->SetNumberOfDivisionsTiledStreaming(4);
  writer->Update();

  return EXIT_SUCCESS;
}
<commit_msg>DOC: missing doc<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

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

// iostream is used for general output
#include <iostream>
#include <stdlib.h>

#include "otbMacro.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMapProjections.h"
#include "itkComplexToModulusImageFilter.h"
#include "otbUnaryImageFunctorWithVectorImageFilter.h"
#include "otbOrthoRectificationFilter.h"
#include "otbMapProjections.h"

int otbOrthoRectificationFilter(int argc, char* argv[])
{
  if (argc != 12)
    {
    std::cout << argv[0] <<
    " <input filename> <output filename> <origin easting> <origin northing>"
    " <x size> <y size> <x spacing> <y spacing> <UTM zone> <UTM hemisphere>"
    " <grid_spacing>"
              << std::endl;

    return EXIT_FAILURE;
    }

  typedef otb::VectorImage<double, 2>                                               VectorImageType;
  typedef otb::ImageFileReader<VectorImageType>                                     ReaderType;
  typedef otb::ImageFileWriter<VectorImageType>                            WriterType;
  typedef otb::UtmInverseProjection                                                 UtmMapProjectionType;
  typedef otb::OrthoRectificationFilter<VectorImageType, VectorImageType, UtmMapProjectionType> OrthoRectifFilterType;

  //Allocate pointer
  ReaderType::Pointer reader = ReaderType::New();
  WriterType::Pointer writer = WriterType::New();

  OrthoRectifFilterType::Pointer orthoRectifFilter = OrthoRectifFilterType::New();
  UtmMapProjectionType::Pointer  utmMapProjection = UtmMapProjectionType::New();

  // Set parameters ...
  reader->SetFileName(argv[1]);
  writer->SetFileName(argv[2]);

  reader->GenerateOutputInformation();
  std::cout << reader->GetOutput() << std::endl;

  orthoRectifFilter->SetInput(reader->GetOutput());

  VectorImageType::IndexType start;
  start[0] = 0;
  start[1] = 0;
  orthoRectifFilter->SetOutputStartIndex(start);

  VectorImageType::SizeType size;
  size[0] = atoi(argv[5]);      // X size
  size[1] = atoi(argv[6]);            //Y size
  orthoRectifFilter->SetOutputSize(size);

  VectorImageType::SpacingType spacing;
  spacing[0] = atof(argv[7]);
  spacing[1] = atof(argv[8]);
  orthoRectifFilter->SetOutputSpacing(spacing);

  VectorImageType::PointType origin;
  origin[0] = strtod(argv[3], NULL);         //Origin easting
  origin[1] = strtod(argv[4], NULL);         //Origin northing
  orthoRectifFilter->SetOutputOrigin(origin);

  utmMapProjection->SetZone(atoi(argv[9]));
  utmMapProjection->SetHemisphere(argv[10][0]);
  orthoRectifFilter->SetMapProjection(utmMapProjection);

  // Displacement Field spacing
  VectorImageType::SpacingType  gridSpacing;
  gridSpacing[0] = atof(argv[11]);
  gridSpacing[1] = -atof(argv[11]);
  orthoRectifFilter->SetDisplacementFieldSpacing(gridSpacing);

  VectorImageType::PixelType no_data(reader->GetOutput()->GetNumberOfComponentsPerPixel());
  no_data.Fill(0);
  orthoRectifFilter->SetEdgePaddingValue(no_data);

  writer->SetInput(orthoRectifFilter->GetOutput());
  writer->SetNumberOfDivisionsTiledStreaming(4);
  writer->Update();

  return EXIT_SUCCESS;
}

int otbOrthoRectificationComplexFilter(int argc, char* argv[])
{
  if (argc != 12)
    {
    std::cout << argv[0] <<
    " <input filename> <output filename> <origin easting> <origin northing> <x size> <y size> <x spacing> <y spacing> <UTM zone> <UTM hemisphere>"
              << std::endl;

    return EXIT_FAILURE;
    }

  typedef otb::VectorImage<std::complex<double>, 2>                                 ComplexVectorImageType;
  typedef otb::VectorImage<double, 2>                                               ModulusVectorImageType;
  typedef otb::UnaryImageFunctorWithVectorImageFilter<
                        ComplexVectorImageType,
                        ModulusVectorImageType,
                        itk::Functor::ComplexToModulus<
                          ComplexVectorImageType::InternalPixelType,
                          ModulusVectorImageType::InternalPixelType
                          >
                        >                                                           ComplexToModulusFilterType;
  typedef otb::ImageFileReader<ComplexVectorImageType>                              ReaderType;
  typedef otb::ImageFileWriter<ModulusVectorImageType>                     WriterType;
  typedef otb::UtmInverseProjection                                                 UtmMapProjectionType;
  typedef otb::OrthoRectificationFilter<ModulusVectorImageType, ModulusVectorImageType, UtmMapProjectionType> OrthoRectifFilterType;

  //Allocate pointer
  ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName(argv[1]);
  reader->GenerateOutputInformation();
  std::cout << reader->GetOutput() << std::endl;

  ComplexToModulusFilterType::Pointer complexToModulus = ComplexToModulusFilterType::New();
  complexToModulus->SetInput(reader->GetOutput());

  UtmMapProjectionType::Pointer  utmMapProjection = UtmMapProjectionType::New();
  OrthoRectifFilterType::Pointer orthoRectifFilter = OrthoRectifFilterType::New();

  orthoRectifFilter->SetInput(complexToModulus->GetOutput());

  ComplexVectorImageType::IndexType start;
  start[0] = 0;
  start[1] = 0;
  orthoRectifFilter->SetOutputStartIndex(start);

  ComplexVectorImageType::SizeType size;
  size[0] = atoi(argv[5]);      // X size
  size[1] = atoi(argv[6]);            //Y size
  orthoRectifFilter->SetOutputSize(size);

  ComplexVectorImageType::SpacingType spacing;
  spacing[0] = atof(argv[7]);
  spacing[1] = atof(argv[8]);
  orthoRectifFilter->SetOutputSpacing(spacing);

  ComplexVectorImageType::PointType origin;
  origin[0] = strtod(argv[3], NULL);         //Origin easting
  origin[1] = strtod(argv[4], NULL);         //Origin northing
  orthoRectifFilter->SetOutputOrigin(origin);

  utmMapProjection->SetZone(atoi(argv[9]));
  utmMapProjection->SetHemisphere(argv[10][0]);
  orthoRectifFilter->SetMapProjection(utmMapProjection);

  // Displacement Field spacing
  ComplexVectorImageType::SpacingType  gridSpacing;
  gridSpacing[0] = atof(argv[11]);
  gridSpacing[1] = -atof(argv[11]);
  orthoRectifFilter->SetDisplacementFieldSpacing(gridSpacing);

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(argv[2]);
  writer->SetInput(orthoRectifFilter->GetOutput());
  writer->SetNumberOfDivisionsTiledStreaming(4);
  writer->Update();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UNetReceiver.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
bool UNetReceiver::PacketCompare::operator()(const UniSetUDP::UDPMessage& lhs,
											const UniSetUDP::UDPMessage& rhs) const
{
//	if( lhs.msg.header.num == rhs.msg.header.num )
//		return (lhs.msg < rhs.msg);

	return lhs.msg.header.num > rhs.msg.header.num;
}
// ------------------------------------------------------------------------------------------
UNetReceiver::UNetReceiver( const std::string s_host, const ost::tpport_t port, SMInterface* smi ):
shm(smi),
recvpause(10),
updatepause(100),
udp(0),
recvTimeout(5000),
lostTimeout(5000),
lostPackets(0),
activated(false),
r_thr(0),
u_thr(0),
pnum(0),
maxDifferens(1000),
waitClean(false),
rnum(0),
maxProcessingCount(100),
icache(200),
cache_init_ok(false)
{
	{
		ostringstream s;
		s << "(" << s_host << ":" << port << ")";
		myname = s.str();
	}

	try
	{
//		ost::IPV4Cidr ci(s_host.c_str());
//		addr = ci.getBroadcast();
//		cerr << "****************** addr: " << addr << endl;
		addr = s_host.c_str();
		udp = new ost::UDPDuplex(addr,port);
	}
	catch( ost::SockException& e )
	{
		ostringstream s;
		s << e.getString() << ": " << e.getSystemErrorString();
		dlog[Debug::CRIT] << myname << "(init): " << s.str() << std::endl;

		throw SystemError(s.str());
	}

	r_thr = new ThreadCreator<UNetReceiver>(this, &UNetReceiver::receive);
	u_thr = new ThreadCreator<UNetReceiver>(this, &UNetReceiver::update);

	ptRecvTimeout.setTiming(recvTimeout);
}
// -----------------------------------------------------------------------------
UNetReceiver::~UNetReceiver()
{
	delete r_thr;
	delete u_thr;
	delete udp;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setReceiveTimeout( timeout_t msec )
{
	recvTimeout = msec;
	ptRecvTimeout.setTiming(msec);
}
// -----------------------------------------------------------------------------
void UNetReceiver::setLostTimeout( timeout_t msec )
{
	lostTimeout = msec;
	ptLostTimeout.setTiming(msec);
}
// -----------------------------------------------------------------------------
void UNetReceiver::setReceivePause( timeout_t msec )
{
	recvpause = msec;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setUpdatePause( timeout_t msec )
{
	updatepause = msec;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setMaxProcessingCount( int set )
{
	maxProcessingCount = set;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setMaxDifferens( unsigned long set )
{
	maxDifferens = set;
}
// -----------------------------------------------------------------------------
void UNetReceiver::start()
{
	if( !activated )
	{
		activated = true;
		u_thr->start();
		r_thr->start();
	}
}
// -----------------------------------------------------------------------------
void UNetReceiver::update()
{
	cerr << "******************* udpate start" << endl;
	while(activated)
	{
		try
		{
			real_update();
		}
		catch( UniSetTypes::Exception& ex)
		{
			dlog[Debug::CRIT] << myname << "(update): " << ex << std::endl;
		}
		catch(...)
		{
			dlog[Debug::CRIT] << myname << "(update): catch ..." << std::endl;
		}

		msleep(updatepause);
	}
}
// -----------------------------------------------------------------------------
void UNetReceiver::real_update()
{
	UniSetUDP::UDPMessage p;
	// обрабатываем пока, очередь либо не опустеет
	// либо обнаружится "дырка" в последовательности
	// но при этом обрабатываем не больше maxProcessingCount
	// за один раз..
	int k = maxProcessingCount;
	while( k>0 )
	{
		{ // lock qpack
			uniset_mutex_lock l(packMutex);
			if( qpack.empty() )
				return;

			p = qpack.top();
			unsigned long sub = labs(p.msg.header.num - pnum);
			if( pnum > 0 )
			{
				// если sub > maxDifferens
				// значит это просто "разрыв"
				// и нам ждать lostTimeout не надо
				// сразу начинаем обрабатывать новые пакеты
				// а если > 1 && < maxDifferens
				// значит это временная "дырка"
				// и надо подождать lostTimeout
				// чтобы констатировать потерю пакета..
				if( sub > 1 && sub < maxDifferens )
				{
					if( !ptLostTimeout.checkTime() )
						return;

					lostPackets++;
				}
				else if( p.msg.header.num == pnum )
				{
				   /* а что делать если идут повторные пакеты ?!
					* для надёжности лучше обрабатывать..
					* для "оптимизации".. лучше игнорировать
					*/
					qpack.pop(); // пока выбрали вариант "оптимизации"
					continue;
				}
			}

			ptLostTimeout.reset();

			// удаляем из очереди, только если
			// всё в порядке с последовательностью..
			qpack.pop();
			pnum = p.msg.header.num;
		} // unlock qpack

		k--;

//		cerr << myname << "(update): " << p.msg.header << endl;

		initCache(p, !cache_init_ok);

		for( size_t i=0; i<p.msg.header.dcount; i++ )
		{
			try
			{
				UniSetUDP::UDPData& d = p.msg.dat[i];
				ItemInfo& ii(icache[i]);
				if( ii.id != d.id )
				{
					dlog[Debug::WARN] << myname << "(update): reinit cache for sid=" << d.id << endl;
					ii.id = d.id;
					shm->initAIterator(ii.ait);
					shm->initDIterator(ii.dit);
				}

//				if( d.id == 121 )
//					cerr << "****** save id=" << d.id << " val=" << d.val << endl;
				if( ii.iotype == UniversalIO::DigitalInput )
					shm->localSaveState(ii.dit,d.id,d.val,shm->ID());
				else if( ii.iotype == UniversalIO::AnalogInput )
					shm->localSaveValue(ii.ait,d.id,d.val,shm->ID());
				else if( ii.iotype == UniversalIO::AnalogOutput )
					shm->localSetValue(ii.ait,d.id,d.val,shm->ID());
				else if( ii.iotype == UniversalIO::DigitalOutput )
					shm->localSetState(ii.dit,d.id,d.val,shm->ID());
				else
				  dlog[Debug::CRIT] << myname << "(update): Unknown iotype for sid=" << d.id << endl;
			}
			catch( UniSetTypes::Exception& ex)
			{
				dlog[Debug::CRIT] << myname << "(update): " << ex << std::endl;
			}
			catch(...)
			{
				dlog[Debug::CRIT] << myname << "(update): catch ..." << std::endl;
			}
		}
	}
}

// -----------------------------------------------------------------------------
void UNetReceiver::stop()
{
	activated = false;
//	msleep(10);
//	u_thr->stop();
//	r_thr->stop();
}
// -----------------------------------------------------------------------------
void UNetReceiver::receive()
{
	cout << myname << ": ******************* receive start" << endl;
	ptRecvTimeout.setTiming(recvTimeout);
	while( activated )
	{
		try
		{
			if( recv() )
			  ptRecvTimeout.reset();
		}
		catch( ost::SockException& e )
		{
			cerr  << myname << "(receive): " << e.getString() << endl;
		}
		catch( UniSetTypes::Exception& ex)
		{
			cerr << myname << "(receive): " << ex << std::endl;
		}
		catch(...)
		{
			cerr << myname << "(receive): catch ..." << std::endl;
		}

		msleep(recvpause);
	}

	cout << myname << ": ************* receive FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
bool UNetReceiver::recv()
{
	if( !udp->isInputReady(recvTimeout) )
		return false;

	size_t ret = udp->UDPReceive::receive(&(pack.msg),sizeof(pack.msg));
	if( ret < sizeof(UniSetUDP::UDPHeader) )
	{
		dlog[Debug::CRIT] << myname << "(receive): FAILED header ret=" << ret << " sizeof=" << sizeof(UniSetUDP::UDPHeader) << endl;
		return false;
	}

	size_t sz = pack.msg.header.dcount * sizeof(UniSetUDP::UDPData) + sizeof(UniSetUDP::UDPHeader);
	if( ret < sz )
	{
		dlog[Debug::CRIT] << myname << "(receive): FAILED data ret=" << ret << " sizeof=" << sz
			  << " packnum=" << pack.msg.header.num << endl;
		return false;
	}

	if( rnum>0 && labs(pack.msg.header.num - rnum) > maxDifferens )
	{
		/* А что делать если мы уже ждём и ещё не "разгребли предыдущее".. а тут уже повторный "разрыв"
		 * Можно откинуть всё.. что сложили во временную очередь и заново "копить" (но тогда теряем информацию)
		 * А можно породолжать складывать во временную, но тогда есть риск "никогда" не разгрести временную
		 * очередь, при "частых обрывах". Потому-что update будет на каждом разрыве ждать ещё lostTimeout..
		 */
		// Пока выбираю.. чистить qtmp. Это будет соотвествовать логике работы с картами у которых ограничен буфер приёма.
		// Обычно "кольцевой". Т.е. если не успели обработать и "вынуть" из буфера информацию.. он будет переписан новыми данными
		if( waitClean )
		{
			dlog[Debug::CRIT] << myname << "(receive): reset qtmp.." << endl;
			while( !qtmp.empty() )
				qtmp.pop();
		}

		waitClean = true;
	}

	rnum = pack.msg.header.num;

#if 0
	cerr << myname << "(receive): recv DATA OK. ret=" << ret << " sizeof=" << sz
		  << " header: " << pack.msg.header
		  << " waitClean=" << waitClean
		  << endl;
	for( size_t i=0; i<pack.msg.header.dcount; i++ )
	{
		UniSetUDP::UDPData& d = pack.msg.dat[i];
		cerr << "****** save id=" << d.id << " val=" << d.val << endl;
	}
#endif

	{	// lock qpack
		uniset_mutex_lock l(packMutex,500);
		if( !waitClean )
		{
			qpack.push(pack);
			return true;
		}

		if( !qpack.empty() )
		{
//			cerr << myname << "(receive): copy to qtmp..."
//							  << " header: " << pack.msg.header
//							  << endl;
			qtmp.push(pack);
		}
		else
		{
//		  	cerr << myname << "(receive): copy from qtmp..." << endl;
			// очередь освободилась..
			// то копируем в неё всё что набралось...
			while( !qtmp.empty() )
			{
				qpack.push(qtmp.top());
				qtmp.pop();
			}

			// не забываем и текущий поместить в очередь..
			qpack.push(pack);
			waitClean = false;
		}
	}	// unlock qpack

	return true;
}
// -----------------------------------------------------------------------------
void UNetReceiver::initIterators()
{
	for( ItemVec::iterator it=icache.begin(); it!=icache.end(); ++it )
	{
		shm->initAIterator(it->ait);
		shm->initDIterator(it->dit);
	}
}
// -----------------------------------------------------------------------------
void UNetReceiver::initCache( UniSetUDP::UDPMessage& pack, bool force )
{
	 if( !force && pack.msg.header.dcount == icache.size() )
		  return;

	 dlog[Debug::INFO] << myname << ": init icache.." << endl;
	 cache_init_ok = true;

	 icache.resize(pack.msg.header.dcount);
	 for( size_t i=0; i<icache.size(); i++ )
	 {
		  ItemInfo& d(icache[i]);
		  if( d.id != pack.msg.dat[i].id )
		  {
				d.id = pack.msg.dat[i].id;
				d.iotype = conf->getIOType(d.id);
				shm->initAIterator(d.ait);
				shm->initDIterator(d.dit);
		  }
	 }
}
// -----------------------------------------------------------------------------
<commit_msg>(UNet2): новая версия (реализована посылка)<commit_after>#include <sstream>
#include "Exceptions.h"
#include "Extensions.h"
#include "UNetReceiver.h"
// -----------------------------------------------------------------------------
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
// -----------------------------------------------------------------------------
bool UNetReceiver::PacketCompare::operator()(const UniSetUDP::UDPMessage& lhs,
											const UniSetUDP::UDPMessage& rhs) const
{
//	if( lhs.msg.header.num == rhs.msg.header.num )
//		return (lhs.msg < rhs.msg);

	return lhs.msg.header.num > rhs.msg.header.num;
}
// ------------------------------------------------------------------------------------------
UNetReceiver::UNetReceiver( const std::string s_host, const ost::tpport_t port, SMInterface* smi ):
shm(smi),
recvpause(10),
updatepause(100),
udp(0),
recvTimeout(5000),
lostTimeout(5000),
lostPackets(0),
activated(false),
r_thr(0),
u_thr(0),
pnum(0),
maxDifferens(1000),
waitClean(false),
rnum(0),
maxProcessingCount(100),
icache(200),
cache_init_ok(false)
{
	{
		ostringstream s;
		s << "(" << s_host << ":" << port << ")";
		myname = s.str();
	}

	try
	{
//		ost::IPV4Cidr ci(s_host.c_str());
//		addr = ci.getBroadcast();
//		cerr << "****************** addr: " << addr << endl;
		addr = s_host.c_str();
		udp = new ost::UDPDuplex(addr,port);
	}
	catch( ost::SockException& e )
	{
		ostringstream s;
		s << e.getString() << ": " << e.getSystemErrorString();
		dlog[Debug::CRIT] << myname << "(init): " << s.str() << std::endl;

		throw SystemError(s.str());
	}

	r_thr = new ThreadCreator<UNetReceiver>(this, &UNetReceiver::receive);
	u_thr = new ThreadCreator<UNetReceiver>(this, &UNetReceiver::update);

	ptRecvTimeout.setTiming(recvTimeout);
}
// -----------------------------------------------------------------------------
UNetReceiver::~UNetReceiver()
{
	delete r_thr;
	delete u_thr;
	delete udp;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setReceiveTimeout( timeout_t msec )
{
	recvTimeout = msec;
	ptRecvTimeout.setTiming(msec);
}
// -----------------------------------------------------------------------------
void UNetReceiver::setLostTimeout( timeout_t msec )
{
	lostTimeout = msec;
	ptLostTimeout.setTiming(msec);
}
// -----------------------------------------------------------------------------
void UNetReceiver::setReceivePause( timeout_t msec )
{
	recvpause = msec;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setUpdatePause( timeout_t msec )
{
	updatepause = msec;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setMaxProcessingCount( int set )
{
	maxProcessingCount = set;
}
// -----------------------------------------------------------------------------
void UNetReceiver::setMaxDifferens( unsigned long set )
{
	maxDifferens = set;
}
// -----------------------------------------------------------------------------
void UNetReceiver::start()
{
	if( !activated )
	{
		activated = true;
		u_thr->start();
		r_thr->start();
	}
}
// -----------------------------------------------------------------------------
void UNetReceiver::update()
{
	cerr << "******************* udpate start" << endl;
	while(activated)
	{
		try
		{
			real_update();
		}
		catch( UniSetTypes::Exception& ex)
		{
			dlog[Debug::CRIT] << myname << "(update): " << ex << std::endl;
		}
		catch(...)
		{
			dlog[Debug::CRIT] << myname << "(update): catch ..." << std::endl;
		}

		msleep(updatepause);
	}
}
// -----------------------------------------------------------------------------
void UNetReceiver::real_update()
{
	UniSetUDP::UDPMessage p;
	// обрабатываем пока, очередь либо не опустеет
	// либо обнаружится "дырка" в последовательности
	// но при этом обрабатываем не больше maxProcessingCount
	// за один раз..
	int k = maxProcessingCount;
	while( k>0 )
	{
		{ // lock qpack
			uniset_mutex_lock l(packMutex);
			if( qpack.empty() )
				return;

			p = qpack.top();
			unsigned long sub = labs(p.msg.header.num - pnum);
			if( pnum > 0 )
			{
				// если sub > maxDifferens
				// значит это просто "разрыв"
				// и нам ждать lostTimeout не надо
				// сразу начинаем обрабатывать новые пакеты
				// а если > 1 && < maxDifferens
				// значит это временная "дырка"
				// и надо подождать lostTimeout
				// чтобы констатировать потерю пакета..
				if( sub > 1 && sub < maxDifferens )
				{
					if( !ptLostTimeout.checkTime() )
						return;

					lostPackets++;
				}
				else if( p.msg.header.num == pnum )
				{
				   /* а что делать если идут повторные пакеты ?!
					* для надёжности лучше обрабатывать..
					* для "оптимизации".. лучше игнорировать
					*/
					qpack.pop(); // пока выбрали вариант "оптимизации"
					continue;
				}
			}

			ptLostTimeout.reset();

			// удаляем из очереди, только если
			// всё в порядке с последовательностью..
			qpack.pop();
			pnum = p.msg.header.num;
		} // unlock qpack

		k--;

//		cerr << myname << "(update): " << p.msg.header << endl;

		initCache(p, !cache_init_ok);

		for( size_t i=0; i<p.msg.header.dcount; i++ )
		{
			try
			{
				UniSetUDP::UDPData& d = p.msg.dat[i];
				ItemInfo& ii(icache[i]);
				if( ii.id != d.id )
				{
					dlog[Debug::WARN] << myname << "(update): reinit cache for sid=" << d.id << endl;
					ii.id = d.id;
					shm->initAIterator(ii.ait);
					shm->initDIterator(ii.dit);
				}

				if( ii.iotype == UniversalIO::DigitalInput )
					shm->localSaveState(ii.dit,d.id,d.val,shm->ID());
				else if( ii.iotype == UniversalIO::AnalogInput )
					shm->localSaveValue(ii.ait,d.id,d.val,shm->ID());
				else if( ii.iotype == UniversalIO::AnalogOutput )
					shm->localSetValue(ii.ait,d.id,d.val,shm->ID());
				else if( ii.iotype == UniversalIO::DigitalOutput )
					shm->localSetState(ii.dit,d.id,d.val,shm->ID());
				else
				  dlog[Debug::CRIT] << myname << "(update): Unknown iotype for sid=" << d.id << endl;
			}
			catch( UniSetTypes::Exception& ex)
			{
				dlog[Debug::CRIT] << myname << "(update): " << ex << std::endl;
			}
			catch(...)
			{
				dlog[Debug::CRIT] << myname << "(update): catch ..." << std::endl;
			}
		}
	}
}

// -----------------------------------------------------------------------------
void UNetReceiver::stop()
{
	activated = false;
//	msleep(10);
//	u_thr->stop();
//	r_thr->stop();
}
// -----------------------------------------------------------------------------
void UNetReceiver::receive()
{
	dlog[Debug::INFO] << myname << ": ******************* receive start" << endl;
	ptRecvTimeout.setTiming(recvTimeout);
	while( activated )
	{
		try
		{
			if( recv() )
			  ptRecvTimeout.reset();
		}
		catch( ost::SockException& e )
		{
			dlog[Debug::WARN] << myname << "(receive): " << e.getString() << endl;
		}
		catch( UniSetTypes::Exception& ex)
		{
			dlog[Debug::WARN] << myname << "(receive): " << ex << std::endl;
		}
		catch(...)
		{
			dlog[Debug::WARN] << myname << "(receive): catch ..." << std::endl;
		}

		msleep(recvpause);
	}

	dlog[Debug::INFO] << myname << ": ************* receive FINISH **********" << endl;
}
// -----------------------------------------------------------------------------
bool UNetReceiver::recv()
{
	if( !udp->isInputReady(recvTimeout) )
		return false;

	size_t ret = udp->UDPReceive::receive(&(pack.msg),sizeof(pack.msg));
	if( ret < sizeof(UniSetUDP::UDPHeader) )
	{
		dlog[Debug::CRIT] << myname << "(receive): FAILED header ret=" << ret << " sizeof=" << sizeof(UniSetUDP::UDPHeader) << endl;
		return false;
	}

	size_t sz = pack.msg.header.dcount * sizeof(UniSetUDP::UDPData) + sizeof(UniSetUDP::UDPHeader);
	if( ret < sz )
	{
		dlog[Debug::CRIT] << myname << "(receive): FAILED data ret=" << ret << " sizeof=" << sz
			  << " packnum=" << pack.msg.header.num << endl;
		return false;
	}

	if( rnum>0 && labs(pack.msg.header.num - rnum) > maxDifferens )
	{
		/* А что делать если мы уже ждём и ещё не "разгребли предыдущее".. а тут уже повторный "разрыв"
		 * Можно откинуть всё.. что сложили во временную очередь и заново "копить" (но тогда теряем информацию)
		 * А можно породолжать складывать во временную, но тогда есть риск "никогда" не разгрести временную
		 * очередь, при "частых обрывах". Потому-что update будет на каждом разрыве ждать ещё lostTimeout..
		 */
		// Пока выбираю.. чистить qtmp. Это будет соотвествовать логике работы с картами у которых ограничен буфер приёма.
		// Обычно "кольцевой". Т.е. если не успели обработать и "вынуть" из буфера информацию.. он будет переписан новыми данными
		if( waitClean )
		{
			dlog[Debug::CRIT] << myname << "(receive): reset qtmp.." << endl;
			while( !qtmp.empty() )
				qtmp.pop();
		}

		waitClean = true;
	}

	rnum = pack.msg.header.num;

#if 0
	cerr << myname << "(receive): recv DATA OK. ret=" << ret << " sizeof=" << sz
		  << " header: " << pack.msg.header
		  << " waitClean=" << waitClean
		  << endl;
	for( size_t i=0; i<pack.msg.header.dcount; i++ )
	{
		UniSetUDP::UDPData& d = pack.msg.dat[i];
		cerr << "****** save id=" << d.id << " val=" << d.val << endl;
	}
#endif

	{	// lock qpack
		uniset_mutex_lock l(packMutex,500);
		if( !waitClean )
		{
			qpack.push(pack);
			return true;
		}

		if( !qpack.empty() )
		{
//			cerr << myname << "(receive): copy to qtmp..."
//							  << " header: " << pack.msg.header
//							  << endl;
			qtmp.push(pack);
		}
		else
		{
//		  	cerr << myname << "(receive): copy from qtmp..." << endl;
			// очередь освободилась..
			// то копируем в неё всё что набралось...
			while( !qtmp.empty() )
			{
				qpack.push(qtmp.top());
				qtmp.pop();
			}

			// не забываем и текущий поместить в очередь..
			qpack.push(pack);
			waitClean = false;
		}
	}	// unlock qpack

	return true;
}
// -----------------------------------------------------------------------------
void UNetReceiver::initIterators()
{
	for( ItemVec::iterator it=icache.begin(); it!=icache.end(); ++it )
	{
		shm->initAIterator(it->ait);
		shm->initDIterator(it->dit);
	}
}
// -----------------------------------------------------------------------------
void UNetReceiver::initCache( UniSetUDP::UDPMessage& pack, bool force )
{
	 if( !force && pack.msg.header.dcount == icache.size() )
		  return;

	 dlog[Debug::INFO] << myname << ": init icache.." << endl;
	 cache_init_ok = true;

	 icache.resize(pack.msg.header.dcount);
	 for( size_t i=0; i<icache.size(); i++ )
	 {
		  ItemInfo& d(icache[i]);
		  if( d.id != pack.msg.dat[i].id )
		  {
				d.id = pack.msg.dat[i].id;
				d.iotype = conf->getIOType(d.id);
				shm->initAIterator(d.ait);
				shm->initDIterator(d.dit);
		  }
	 }
}
// -----------------------------------------------------------------------------
<|endoftext|>


<commit_before>#include "builtin/io.hpp"
#include "builtin/bytearray.hpp"
#include "builtin/class.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/string.hpp"

#include "vm.hpp"
#include "objectmemory.hpp"

namespace rubinius {
  void IO::init(STATE) {
    GO(io).set(state->new_class("IO", G(object), IO::fields));
    GO(iobuffer).set(state->new_class("Buffer", G(object), IOBuffer::fields, G(io)));
  }

  IOBuffer* IOBuffer::create(STATE, size_t bytes) {
    IOBuffer* buf = (IOBuffer*)state->new_object(G(iobuffer));
    SET(buf, storage, ByteArray::create(state, bytes));
    SET(buf, total, Fixnum::from(bytes));
    SET(buf, used, Fixnum::from(0));

    return buf;
  }

  IO* IO::create(STATE, int fd) {
    IO* io = (IO*)state->new_object(G(io));
    SET(io, descriptor, Integer::from(state, fd));
    return io;
  }

  void IO::initialize(STATE, int fd, char* mode) {
    SET(this, descriptor, Integer::from(state, fd));
    SET(this, mode, String::create(state, mode));
  }

  native_int IO::to_fd() {
    return descriptor->to_native();
  }

  OBJECT IO::write(STATE, String* buf) {
    ssize_t cnt = ::write(this->to_fd(), buf->data->bytes, buf->size());

    // TODO: RAISE_FROM_ERRNO
    if(cnt == -1) {
      throw std::runtime_error("IO::write primitive failed. (TODO RAISE_FROM_ERRNO)");
    }

    return Integer::from(state, cnt);
  }

  void IOBuffer::read_bytes(size_t bytes) {
    used = Fixnum::from(used->to_native() + bytes);
  }

  char* IOBuffer::byte_address() {
    return (char*)storage->bytes;
  }

  size_t IOBuffer::left() {
    return total->to_native() - used->to_native();
  }

  char* IOBuffer::at_unused() {
    char* start = (char*)storage->bytes;
    start += used->to_native();
    return start;
  }
};
<commit_msg>Hook up IO's object type<commit_after>#include "builtin/io.hpp"
#include "builtin/bytearray.hpp"
#include "builtin/class.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/string.hpp"

#include "vm.hpp"
#include "objectmemory.hpp"

namespace rubinius {
  void IO::init(STATE) {
    GO(io).set(state->new_class("IO", G(object), IO::fields));
    G(io)->set_object_type(IOType);

    GO(iobuffer).set(state->new_class("Buffer", G(object), IOBuffer::fields, G(io)));
    G(iobuffer)->set_object_type(IOBufferType);
  }

  IOBuffer* IOBuffer::create(STATE, size_t bytes) {
    IOBuffer* buf = (IOBuffer*)state->new_object(G(iobuffer));
    SET(buf, storage, ByteArray::create(state, bytes));
    SET(buf, total, Fixnum::from(bytes));
    SET(buf, used, Fixnum::from(0));

    return buf;
  }

  IO* IO::create(STATE, int fd) {
    IO* io = (IO*)state->new_object(G(io));
    SET(io, descriptor, Integer::from(state, fd));
    return io;
  }

  void IO::initialize(STATE, int fd, char* mode) {
    SET(this, descriptor, Integer::from(state, fd));
    SET(this, mode, String::create(state, mode));
  }

  native_int IO::to_fd() {
    return descriptor->to_native();
  }

  OBJECT IO::write(STATE, String* buf) {
    ssize_t cnt = ::write(this->to_fd(), buf->data->bytes, buf->size());

    // TODO: RAISE_FROM_ERRNO
    if(cnt == -1) {
      throw std::runtime_error("IO::write primitive failed. (TODO RAISE_FROM_ERRNO)");
    }

    return Integer::from(state, cnt);
  }

  void IOBuffer::read_bytes(size_t bytes) {
    used = Fixnum::from(used->to_native() + bytes);
  }

  char* IOBuffer::byte_address() {
    return (char*)storage->bytes;
  }

  size_t IOBuffer::left() {
    return total->to_native() - used->to_native();
  }

  char* IOBuffer::at_unused() {
    char* start = (char*)storage->bytes;
    start += used->to_native();
    return start;
  }
};
<|endoftext|>


<commit_before>namespace factor
{

/* Some functions for converting floating point numbers to binary
representations and vice versa */

union double_bits_pun {
	double x;
	u64 y;
};

inline static u64 double_bits(double x)
{
	double_bits_pun b;
	b.x = x;
	return b.y;
}

inline static double bits_double(u64 y)
{
	double_bits_pun b;
	b.y = y;
	return b.x;
}

union float_bits_pun {
	float x;
	u32 y;
};

inline static u32 float_bits(float x)
{
	float_bits_pun b;
	b.x = x;
	return b.y;
}

inline static float bits_float(u32 y)
{
	float_bits_pun b;
	b.y = y;
	return b.x;
}

}
<commit_msg>VM: Refactor float_bits.hpp to Factor style<commit_after>namespace factor {

/* Some functions for converting floating point numbers to binary
representations and vice versa */

union double_bits_pun {
  double x;
  u64 y;
};

inline static u64 double_bits(double x) {
  double_bits_pun b;
  b.x = x;
  return b.y;
}

inline static double bits_double(u64 y) {
  double_bits_pun b;
  b.y = y;
  return b.x;
}

union float_bits_pun {
  float x;
  u32 y;
};

inline static u32 float_bits(float x) {
  float_bits_pun b;
  b.x = x;
  return b.y;
}

inline static float bits_float(u32 y) {
  float_bits_pun b;
  b.y = y;
  return b.x;
}

}
<|endoftext|>


<commit_before>#include "main.h"
#include "CNetwork.h"
#include "CServer.h"
#include "CUtils.h"

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

#include "format.h"

void CNetwork::NetAlive(const boost::system::error_code &error_code, bool from_write)
{
	if (from_write == false)
	{
		if (m_Socket.is_open())
		{
			static string empty_data("\n");
			m_Socket.async_send(asio::buffer(empty_data), boost::bind(&CNetwork::NetAlive, this, boost::asio::placeholders::error, true));
		}
		m_AliveTimer.expires_from_now(boost::posix_time::seconds(60));
		m_AliveTimer.async_wait(boost::bind(&CNetwork::NetAlive, this, boost::asio::placeholders::error, false));
	}
}

void CNetwork::Connect(string ip, unsigned short port, unsigned short query_port)
{
	m_SocketDest = tcp::endpoint(asio::ip::address::from_string(ip), query_port);
	m_ServerPort = port;
	AsyncConnect();
	m_IoThread = new thread(boost::bind(&asio::io_service::run, boost::ref(m_IoService)));

	Execute(fmt::format("use port={}", m_ServerPort));
}

void CNetwork::Disconnect()
{
	if (m_Socket.is_open() == false)
		return;

	m_Socket.close();
	m_IoService.stop();

	if (m_IoThread != nullptr)
	{
		if (m_IoThread->get_id() != boost::this_thread::get_id())
			m_IoThread->join();
		delete m_IoThread;
		m_IoThread = nullptr;
	}
}

void CNetwork::AsyncRead()
{
	asio::async_read_until(m_Socket, m_ReadStreamBuf, '\r', boost::bind(&CNetwork::OnRead, this, _1));
}

void CNetwork::AsyncWrite(string &data)
{
	m_CmdWriteBuffer = data;
	if (data.at(data.length()-1) != '\n')
		m_CmdWriteBuffer.push_back('\n');

	m_Socket.async_send(asio::buffer(m_CmdWriteBuffer), boost::bind(&CNetwork::OnWrite, this, _1));
}

void CNetwork::AsyncConnect()
{
	if (m_Socket.is_open())
		m_Socket.close();

	m_Socket.async_connect(m_SocketDest, boost::bind(&CNetwork::OnConnect, this, _1));
}

void CNetwork::OnConnect(const boost::system::error_code &error_code)
{
	if (error_code.value() == 0)
	{
		AsyncRead();
	}
	else
	{
		logprintf(">> plugin.TSConnector: Error while connecting to server: \"%s\"", error_code.message().c_str());
		Disconnect();
	}
}

/*
	- result data is sent as a string which ends with "\n\r"
	- the Teamspeak3 server can send multiple strings
	- the end of a result set is always an error result string
*/
void CNetwork::OnRead(const boost::system::error_code &error_code)
{
	if (error_code.value() == 0)
	{
		static vector<string> captured_data;
		std::istream tmp_stream(&m_ReadStreamBuf);
		string read_data;
		std::getline(tmp_stream, read_data, '\r');

#ifdef _DEBUG
		if (read_data.length() < 512)
			logprintf(">>>> %s", read_data.c_str());
		else
		{
			string shortened_data(read_data);
			shortened_data.resize(256);
			logprintf(">>>> %s", shortened_data.c_str());
		}
#endif

		//regex: parse error
		//if this is an error message, it means that no other result data will come
		static const boost::regex error_rx("error id=([0-9]+) msg=([^ \n]+)");
		boost::smatch error_rx_result;
		if (boost::regex_search(read_data, error_rx_result, error_rx))
		{
			if (error_rx_result[1].str() == "0")
			{
				for (auto i = captured_data.begin(); i != captured_data.end(); ++i)
				{
					string &data = *i;
					if (data.find('|') != string::npos) //multiple data rows with '|' as delimiter
					{
						vector<string> result_set;
						size_t delim_pos = 0;
						do
						{
							size_t old_delim_pos = delim_pos;
							delim_pos = data.find('|', delim_pos);
							string row = data.substr(old_delim_pos, delim_pos - old_delim_pos);
							result_set.push_back(row);
						} while (delim_pos != string::npos && ++delim_pos);

						i = captured_data.erase(i);
						for (auto j = result_set.begin(), jend = result_set.end(); j != jend; ++j)
							i = captured_data.insert(i, *j);
					}
				}

				//call callback and send next command
				m_CmdQueueMutex.lock();
				if (m_CmdQueue.empty() == false)
				{
					ReadCallback_t &callback = m_CmdQueue.front().get<1>();
					m_CmdQueueMutex.unlock();
					if (callback.empty() == false)
						callback(captured_data); //calls the callback
					m_CmdQueueMutex.lock();
					m_CmdQueue.pop();

					if (m_CmdQueue.empty() == false)
						AsyncWrite(m_CmdQueue.front().get<0>());
				}
				m_CmdQueueMutex.unlock();
			}
			else
			{
				string error_str(error_rx_result[2].str());
				CUtils::Get()->UnEscapeString(error_str);

				logprintf(">> plugin.TSConnector: Error while executing \"%s\": %s (#%s)",
					m_CmdQueue.front().get<0>().c_str(), error_str.c_str(), error_rx_result[1].str().c_str());
				m_CmdQueue.pop();
			}

			captured_data.clear();
		}
		else if (read_data.find("notify") == 0)
		{
			//check if notify is duplicate
			static string last_notify_data;
			static const vector<string> duplicate_notifies{
				"notifyclientmoved",
				"notifycliententerview",
				"notifyclientleftview"
			};
			bool is_duplicate = false;

			for (auto &s : duplicate_notifies)
			{
				if (read_data.find(s) == 0)
				{
					if (last_notify_data == read_data)
						is_duplicate = true;

					break;
				}
			}

			if (is_duplicate == false)
			{
				//notify event
				boost::smatch event_result;
				for (auto &event : m_EventList)
				{
					if (boost::regex_search(read_data, event_result, event.get<0>()))
					{
						event.get<1>()(event_result);
						break;
					}
				}
			}

			last_notify_data = read_data;
		}
		else
		{
			//stack the result data if it is not an error or notification message
			captured_data.push_back(read_data);
		}

		AsyncRead();
	}
	else if (error_code == asio::error::eof)
	{
		AsyncConnect();
	}
	else
		logprintf(">> plugin.TSConnector: Error while reading: %s (#%d)", error_code.message().c_str(), error_code.value());
}

void CNetwork::OnWrite(const boost::system::error_code &error_code)
{
#ifdef _DEBUG
	logprintf("<<<< %s", m_CmdWriteBuffer.c_str());
#endif
	m_CmdWriteBuffer.clear();
	if (error_code.value() != 0)
		logprintf(">> plugin.TSConnector: Error while writing: %s (#%d)", error_code.message().c_str(), error_code.value());
}

void CNetwork::Execute(string cmd, ReadCallback_t callback)
{
	boost::lock_guard<boost::mutex> queue_lock_guard(m_CmdQueueMutex);
	m_CmdQueue.push(boost::make_tuple(boost::move(cmd), boost::move(callback)));
	if (m_CmdQueue.size() == 1)
		AsyncWrite(m_CmdQueue.front().get<0>());
}

<commit_msg>code improvements<commit_after>#include "main.h"
#include "CNetwork.h"
#include "CServer.h"
#include "CUtils.h"

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

#include "format.h"

void CNetwork::NetAlive(const boost::system::error_code &error_code, bool from_write)
{
	if (from_write == true)
		return;

	if (m_Socket.is_open())
	{
		static string empty_data("\n");
		m_Socket.async_send(asio::buffer(empty_data), boost::bind(&CNetwork::NetAlive, this, boost::asio::placeholders::error, true));
	}
	m_AliveTimer.expires_from_now(boost::posix_time::seconds(60));
	m_AliveTimer.async_wait(boost::bind(&CNetwork::NetAlive, this, boost::asio::placeholders::error, false));
}

void CNetwork::Connect(string ip, unsigned short port, unsigned short query_port)
{
	m_SocketDest = tcp::endpoint(asio::ip::address::from_string(ip), query_port);
	m_ServerPort = port;
	AsyncConnect();
	m_IoThread = new thread(boost::bind(&asio::io_service::run, boost::ref(m_IoService)));

	Execute(fmt::format("use port={}", m_ServerPort));
}

void CNetwork::Disconnect()
{
	if (m_Socket.is_open() == false)
		return;

	m_Socket.close();
	m_IoService.stop();

	if (m_IoThread != nullptr)
	{
		if (m_IoThread->get_id() != boost::this_thread::get_id())
			m_IoThread->join();
		delete m_IoThread;
		m_IoThread = nullptr;
	}
}

void CNetwork::AsyncRead()
{
	asio::async_read_until(m_Socket, m_ReadStreamBuf, '\r', boost::bind(&CNetwork::OnRead, this, _1));
}

void CNetwork::AsyncWrite(string &data)
{
	m_CmdWriteBuffer = data;
	if (data.at(data.length()-1) != '\n')
		m_CmdWriteBuffer.push_back('\n');

	m_Socket.async_send(asio::buffer(m_CmdWriteBuffer), boost::bind(&CNetwork::OnWrite, this, _1));
}

void CNetwork::AsyncConnect()
{
	if (m_Socket.is_open())
		m_Socket.close();

	m_Socket.async_connect(m_SocketDest, boost::bind(&CNetwork::OnConnect, this, _1));
}

void CNetwork::OnConnect(const boost::system::error_code &error_code)
{
	if (error_code.value() == 0)
	{
		AsyncRead();
	}
	else
	{
		logprintf(">> plugin.TSConnector: Error while connecting to server: \"%s\"", error_code.message().c_str());
		Disconnect();
	}
}

/*
	- result data is sent as a string which ends with "\n\r"
	- the Teamspeak3 server can send multiple strings
	- the end of a result set is always an error result string
*/
void CNetwork::OnRead(const boost::system::error_code &error_code)
{
	if (error_code.value() == 0)
	{
		static vector<string> captured_data;
		std::istream tmp_stream(&m_ReadStreamBuf);
		string read_data;
		std::getline(tmp_stream, read_data, '\r');

#ifdef _DEBUG
		if (read_data.length() < 512)
			logprintf(">>>> %s", read_data.c_str());
		else
		{
			string shortened_data(read_data);
			shortened_data.resize(256);
			logprintf(">>>> %s", shortened_data.c_str());
		}
#endif

		//regex: parse error
		//if this is an error message, it means that no other result data will come
		static const boost::regex error_rx("error id=([0-9]+) msg=([^ \n]+)");
		boost::smatch error_rx_result;
		if (boost::regex_search(read_data, error_rx_result, error_rx))
		{
			if (error_rx_result[1].str() == "0")
			{
				for (auto i = captured_data.begin(); i != captured_data.end(); ++i)
				{
					string &data = *i;
					if (data.find('|') != string::npos) //multiple data rows with '|' as delimiter
					{
						vector<string> result_set;
						size_t delim_pos = 0;
						do
						{
							size_t old_delim_pos = delim_pos;
							delim_pos = data.find('|', delim_pos);
							string row = data.substr(old_delim_pos, delim_pos - old_delim_pos);
							result_set.push_back(row);
						} while (delim_pos != string::npos && ++delim_pos);

						i = captured_data.erase(i);
						for (auto j = result_set.begin(), jend = result_set.end(); j != jend; ++j)
							i = captured_data.insert(i, *j);
					}
				}

				//call callback and send next command
				m_CmdQueueMutex.lock();
				if (m_CmdQueue.empty() == false)
				{
					ReadCallback_t &callback = m_CmdQueue.front().get<1>();
					m_CmdQueueMutex.unlock();
					if (callback.empty() == false)
						callback(captured_data); //calls the callback
					m_CmdQueueMutex.lock();
					m_CmdQueue.pop();

					if (m_CmdQueue.empty() == false)
						AsyncWrite(m_CmdQueue.front().get<0>());
				}
				m_CmdQueueMutex.unlock();
			}
			else
			{
				string error_str(error_rx_result[2].str());
				CUtils::Get()->UnEscapeString(error_str);

				logprintf(">> plugin.TSConnector: Error while executing \"%s\": %s (#%s)",
					m_CmdQueue.front().get<0>().c_str(), error_str.c_str(), error_rx_result[1].str().c_str());
				m_CmdQueue.pop();
			}

			captured_data.clear();
		}
		else if (read_data.find("notify") == 0)
		{
			//check if notify is duplicate
			static string last_notify_data;
			static const vector<string> duplicate_notifies{
				"notifyclientmoved",
				"notifycliententerview",
				"notifyclientleftview"
			};
			bool is_duplicate = false;

			for (auto &s : duplicate_notifies)
			{
				if (read_data.find(s) == 0)
				{
					if (last_notify_data == read_data)
						is_duplicate = true;

					break;
				}
			}

			if (is_duplicate == false)
			{
				//notify event
				boost::smatch event_result;
				for (auto &event : m_EventList)
				{
					if (boost::regex_search(read_data, event_result, event.get<0>()))
					{
						event.get<1>()(event_result);
						break;
					}
				}
			}

			last_notify_data = read_data;
		}
		else
		{
			//stack the result data if it is not an error or notification message
			captured_data.push_back(read_data);
		}

		AsyncRead();
	}
	else if (error_code == asio::error::eof)
	{
		AsyncConnect();
	}
	else
		logprintf(">> plugin.TSConnector: Error while reading: %s (#%d)", error_code.message().c_str(), error_code.value());
}

void CNetwork::OnWrite(const boost::system::error_code &error_code)
{
#ifdef _DEBUG
	logprintf("<<<< %s", m_CmdWriteBuffer.c_str());
#endif
	m_CmdWriteBuffer.clear();
	if (error_code.value() != 0)
		logprintf(">> plugin.TSConnector: Error while writing: %s (#%d)", error_code.message().c_str(), error_code.value());
}

void CNetwork::Execute(string cmd, ReadCallback_t callback)
{
	boost::lock_guard<boost::mutex> queue_lock_guard(m_CmdQueueMutex);
	m_CmdQueue.push(boost::make_tuple(boost::move(cmd), boost::move(callback)));
	if (m_CmdQueue.size() == 1)
		AsyncWrite(m_CmdQueue.front().get<0>());
}
<|endoftext|>


<commit_before>#include "EdgeHeap.h"
#include <cmath>

namespace ysk {

using Edge = LightCompleteGraph::Edge;
using EdgeWeight = LightCompleteGraph::EdgeWeight;
using EdgeId = LightCompleteGraph::EdgeId;
using NodeId = LightCompleteGraph::NodeId;

EdgeHeap::EdgeHeap(LightCompleteGraph& param_graph, bool param_pruneZeroEdges) :
  pruneZeroEdges(param_pruneZeroEdges),
  graph(param_graph),
  unprocessed(0),
  icf(param_graph.numEdges(), 0.0),
  icp(param_graph.numEdges(), 0.0),
  edge2forb_rank(2*param_graph.numEdges(), 0),
  edge2perm_rank(2*param_graph.numEdges(), 0)
{
  initInducedCosts();
}

void EdgeHeap::initInducedCosts() {
  if (verbosity >= 1)
    std::cout<<"Compute induced cost."<<std::endl;
  // preprocessing: sorted vector of non-zero neighbours for each node
  std::vector<std::vector<NodeId>> nonZeroNeighbours;
  for (NodeId u = 0; u < graph.numNodes(); u++) {
    std::vector<NodeId> n;
    for (NodeId v = 0; v < graph.numNodes(); v++) {
      if (u != v && graph.getWeight(Edge(u,v)) != 0.0) {
	n.push_back(v);
      }
    }
    nonZeroNeighbours.push_back(n);
  }

  // compute array: edge -> icf/icp
  for (NodeId u = 0; u < graph.numNodes(); u++) {
    if (verbosity >= 1)
      std::cout<<"Completed "<<(((2*graph.numNodes()-u)*(u+1)/2)*100/graph.numEdges())<<"%\r"<<std::flush;
    for (NodeId v = u + 1; v < graph.numNodes(); v++) {
      // iterate over all edges uv
      Edge uv(u,v);
      EdgeWeight w_uv = graph.getWeight(uv);
      EdgeId id = uv.id();

      if (w_uv == 0.0 || w_uv == LightCompleteGraph::Forbidden || w_uv == LightCompleteGraph::Permanent) {
	icf[id] = LightCompleteGraph::Forbidden;
	icp[id] = LightCompleteGraph::Forbidden;
	continue;
      } else {
	unprocessed++;
      }

      // costs for the edge uv itself
      if (w_uv >= 0) {
	icf[id] += w_uv;	// costs for removing uv
      } else {
	icp[id] += -w_uv;	// costs for adding uv
      }

      // look at all triangles uvw containing uv. Triangles with a zero edge can be ignored
      std::vector<NodeId> w_vec;
      std::set_intersection(nonZeroNeighbours[u].begin(), nonZeroNeighbours[u].end(), nonZeroNeighbours[v].begin(), nonZeroNeighbours[v].end(), back_inserter(w_vec));

      for (NodeId w : w_vec) {
	Edge uw(u,w);
        Edge vw(v,w);
        EdgeWeight w_uw = graph.getWeight(uw);
        EdgeWeight w_vw = graph.getWeight(vw);
	icf[id] += getIcf(w_uw, w_vw);
        icp[id] += getIcp(w_uw, w_vw);
      }
    }
  }

  for (unsigned int i = 0; i < icf.size(); i++){
    if(std::isnan(icf[i])) {
      std::cout<<"NaN! in icf"<<std::endl;
      break;
    }
    if(std::isnan(icp[i])) {
      std::cout<<"NaN! in icp"<<std::endl;
      break;
    }
  }

  // sort edges by icf and icp values
  for (EdgeId i = 0; i < graph.numEdges(); i++) {
    forb_rank2edge.push_back(i);
    perm_rank2edge.push_back(i);
  }

  std::sort(forb_rank2edge.begin(), forb_rank2edge.end(), [this] (EdgeId& a, EdgeId& b) { return icf[a] > icf[b]; });
  std::sort(perm_rank2edge.begin(), perm_rank2edge.end(), [this] (EdgeId& a, EdgeId& b) { return icp[a] > icp[b]; });

  for (EdgeId i = 0; i < graph.numEdges(); i++) {
    icf.push_back(LightCompleteGraph::Forbidden);
    icp.push_back(LightCompleteGraph::Forbidden);
    forb_rank2edge.push_back(graph.numEdges()+i);
    perm_rank2edge.push_back(graph.numEdges()+i);
  }

  // save index in sorted vectors for each edge
  for (EdgeId i = 0; i < 2*graph.numEdges(); i++) {
    edge2forb_rank[forb_rank2edge[i]] = i;
    edge2perm_rank[perm_rank2edge[i]] = i;
  }
}

Edge EdgeHeap::getMaxIcfEdge() const {
  if (forb_rank2edge.size() <= 0) {
    return LightCompleteGraph::InvalidEdge;
  }
  EdgeId ei = forb_rank2edge[0];
  if (icf[ei] < 0) {
    return LightCompleteGraph::InvalidEdge;
  }
  NodeId u = std::ceil(std::sqrt(2*(ei+1)+0.25) - 0.5);
  NodeId v = ei - u * (u-1) / 2;
  return Edge(u, v);
}

Edge EdgeHeap::getMaxIcpEdge() const {
  if (perm_rank2edge.size() <= 0) {
    return LightCompleteGraph::InvalidEdge;
  }
  EdgeId ei = perm_rank2edge[0];
  if (icp[ei] < 0) {
    return LightCompleteGraph::InvalidEdge;
  }
  NodeId u = std::ceil(std::sqrt(2*(ei+1)+0.25) - 0.5);
  NodeId v = ei - u * (u-1) / 2;
  return Edge(u, v);
}

EdgeWeight EdgeHeap::getIcf(const Edge e) const {
  return icf[e.id()];
}

EdgeWeight EdgeHeap::getIcp(const Edge e) const {
  return icp[e.id()];
}

void EdgeHeap::increaseIcf(const Edge e, const EdgeWeight w) {
  EdgeId id = e.id();
  if (w != 0 && icf[id] >= 0) {
    icf[id] += w;
    icf[id] = std::max(icf[id], 0.0);
    updateHeap(forb_rank2edge, id, w, edge2forb_rank, icf);
  }
}

void EdgeHeap::increaseIcp(const Edge e, const EdgeWeight w) {
  EdgeId id = e.id();
  if (w != 0 && icp[id] >= 0) {
    icp[id] += w;
    icp[id] = std::max(icp[id], 0.0);
    updateHeap(perm_rank2edge, id, w, edge2perm_rank, icp);
  }
}

void EdgeHeap::removeEdge(const Edge e) {
  EdgeId id = e.id();
  if (icf[id] != LightCompleteGraph::Forbidden && icp[id] != LightCompleteGraph::Forbidden) {
    icf[id] = LightCompleteGraph::Forbidden;
    icp[id] = LightCompleteGraph::Forbidden;
    updateHeap(forb_rank2edge, id, LightCompleteGraph::Forbidden, edge2forb_rank, icf);
    updateHeap(perm_rank2edge, id, LightCompleteGraph::Forbidden, edge2perm_rank, icp);
    unprocessed--;
  }
}

LightCompleteGraph::EdgeWeight EdgeHeap::getIcf(const EdgeWeight uw, const EdgeWeight vw) const {
  if (uw > 0 && vw > 0) {
    // if both other edges present, remove the cheapest of both
    return std::min(uw, vw);
  } else {
    return 0;
  }
}

LightCompleteGraph::EdgeWeight EdgeHeap::getIcp(const EdgeWeight uw, const EdgeWeight vw) const {
  if (uw < 0 && vw > 0) {
    return std::min(vw, -uw); 	// either add uw or remove vw
  } else if (uw > 0 && vw < 0) {
    return std::min(-vw, uw); 	// either add vw or remove uw
  } else {
    return 0;
  }
}

int EdgeHeap::numUnprocessed() const {
  return unprocessed;
}

void EdgeHeap::updateHeap(std::vector<EdgeId>& heap, const EdgeId e, const EdgeWeight change, std::vector<EdgeId>& index, const std::vector<EdgeWeight>& score) {
  unsigned int pos = index[e];
  if (change > 0) {
    // value increased -> move edge upwards in heap
    while(score[heap[pos/2]] < score[heap[pos]]) {
      // swap pos and pos/2
      std::swap(heap[pos], heap[pos/2]);
      index[heap[pos]] = pos;
      index[heap[pos/2]] = pos/2;
      pos = pos/2;
    }
  } else {
  // value decreased -> move edge downwards in heap
  while((2*pos < heap.size() && score[heap[pos]] < score[heap[2*pos]])
      || (2*pos+1 < heap.size() && score[heap[pos]] < score[heap[2*pos+1]]) ) {
    if (2*pos+1 < heap.size() && score[heap[2*pos]] < score[heap[2*pos+1]]) {
      // element 2*pos+1 exists and is larger than 2*pos -> swap pos with 2*pos+1
      std::swap(heap[pos], heap[2*pos+1]);
      index[heap[pos]] = pos;
      index[heap[pos*2+1]] = pos*2+1;
      pos = 2*pos+1;
    } else {
      // else swap with 2*pos
      std::swap(heap[pos], heap[2*pos]);
      index[heap[pos]] = pos;
      index[heap[pos*2]] = pos*2;
      pos = 2*pos;
    }
  }
}
//   bool wrong = false;
//   unsigned int where = 0;
//   for (unsigned int i = 0; i < heap.size()/2; i++) {
//     if (score[heap[i]] < score[heap[2*i]]) {
//       wrong = true;
//       where = i;
//     }
//     if (2*i+1 < heap.size() && score[heap[i]] < score[heap[2*i+1]]) {
//       wrong = true;
//       where = i;
//     }
//   }
//   if (wrong) {
//     std::cout<<"Error in heap ("<<where<<") "<<score[heap[where/2]]<<" >= "<<score[heap[where]]<<" >= "<<score[heap[2*where]]<<" & "<<score[heap[2*where+1]]<<std::endl;
//   }
}

} // namespace ysk<commit_msg>Fix heuristic calculation crash on verbosity >= 1<commit_after>#include "EdgeHeap.h"
#include <cmath>

namespace ysk {

using Edge = LightCompleteGraph::Edge;
using EdgeWeight = LightCompleteGraph::EdgeWeight;
using EdgeId = LightCompleteGraph::EdgeId;
using NodeId = LightCompleteGraph::NodeId;

EdgeHeap::EdgeHeap(LightCompleteGraph& param_graph, bool param_pruneZeroEdges) :
  pruneZeroEdges(param_pruneZeroEdges),
  graph(param_graph),
  unprocessed(0),
  icf(param_graph.numEdges(), 0.0),
  icp(param_graph.numEdges(), 0.0),
  edge2forb_rank(2*param_graph.numEdges(), 0),
  edge2perm_rank(2*param_graph.numEdges(), 0)
{
  initInducedCosts();
}

void EdgeHeap::initInducedCosts() {
  if (verbosity >= 1)
    std::cout<<"Compute induced cost."<<std::endl;
  // preprocessing: sorted vector of non-zero neighbours for each node
  std::vector<std::vector<NodeId>> nonZeroNeighbours;
  for (NodeId u = 0; u < graph.numNodes(); u++) {
    std::vector<NodeId> n;
    for (NodeId v = 0; v < graph.numNodes(); v++) {
      if (u != v && graph.getWeight(Edge(u,v)) != 0.0) {
	n.push_back(v);
      }
    }
    nonZeroNeighbours.push_back(n);
  }

  // compute array: edge -> icf/icp
  for (NodeId u = 0; u < graph.numNodes(); u++) {
    if (verbosity >= 1 && graph.numEdges() > 0)
      std::cout<<"Completed "<<(((2*graph.numNodes()-u)*(u+1)/2)*100/graph.numEdges())<<"%\r"<<std::flush;
    for (NodeId v = u + 1; v < graph.numNodes(); v++) {
      // iterate over all edges uv
      Edge uv(u,v);
      EdgeWeight w_uv = graph.getWeight(uv);
      EdgeId id = uv.id();

      if (w_uv == 0.0 || w_uv == LightCompleteGraph::Forbidden || w_uv == LightCompleteGraph::Permanent) {
	icf[id] = LightCompleteGraph::Forbidden;
	icp[id] = LightCompleteGraph::Forbidden;
	continue;
      } else {
	unprocessed++;
      }

      // costs for the edge uv itself
      if (w_uv >= 0) {
	icf[id] += w_uv;	// costs for removing uv
      } else {
	icp[id] += -w_uv;	// costs for adding uv
      }

      // look at all triangles uvw containing uv. Triangles with a zero edge can be ignored
      std::vector<NodeId> w_vec;
      std::set_intersection(nonZeroNeighbours[u].begin(), nonZeroNeighbours[u].end(), nonZeroNeighbours[v].begin(), nonZeroNeighbours[v].end(), back_inserter(w_vec));

      for (NodeId w : w_vec) {
	Edge uw(u,w);
        Edge vw(v,w);
        EdgeWeight w_uw = graph.getWeight(uw);
        EdgeWeight w_vw = graph.getWeight(vw);
	icf[id] += getIcf(w_uw, w_vw);
        icp[id] += getIcp(w_uw, w_vw);
      }
    }
  }

  for (unsigned int i = 0; i < icf.size(); i++){
    if(std::isnan(icf[i])) {
      std::cout<<"NaN! in icf"<<std::endl;
      break;
    }
    if(std::isnan(icp[i])) {
      std::cout<<"NaN! in icp"<<std::endl;
      break;
    }
  }

  // sort edges by icf and icp values
  for (EdgeId i = 0; i < graph.numEdges(); i++) {
    forb_rank2edge.push_back(i);
    perm_rank2edge.push_back(i);
  }

  std::sort(forb_rank2edge.begin(), forb_rank2edge.end(), [this] (EdgeId& a, EdgeId& b) { return icf[a] > icf[b]; });
  std::sort(perm_rank2edge.begin(), perm_rank2edge.end(), [this] (EdgeId& a, EdgeId& b) { return icp[a] > icp[b]; });

  for (EdgeId i = 0; i < graph.numEdges(); i++) {
    icf.push_back(LightCompleteGraph::Forbidden);
    icp.push_back(LightCompleteGraph::Forbidden);
    forb_rank2edge.push_back(graph.numEdges()+i);
    perm_rank2edge.push_back(graph.numEdges()+i);
  }

  // save index in sorted vectors for each edge
  for (EdgeId i = 0; i < 2*graph.numEdges(); i++) {
    edge2forb_rank[forb_rank2edge[i]] = i;
    edge2perm_rank[perm_rank2edge[i]] = i;
  }
}

Edge EdgeHeap::getMaxIcfEdge() const {
  if (forb_rank2edge.size() <= 0) {
    return LightCompleteGraph::InvalidEdge;
  }
  EdgeId ei = forb_rank2edge[0];
  if (icf[ei] < 0) {
    return LightCompleteGraph::InvalidEdge;
  }
  NodeId u = std::ceil(std::sqrt(2*(ei+1)+0.25) - 0.5);
  NodeId v = ei - u * (u-1) / 2;
  return Edge(u, v);
}

Edge EdgeHeap::getMaxIcpEdge() const {
  if (perm_rank2edge.size() <= 0) {
    return LightCompleteGraph::InvalidEdge;
  }
  EdgeId ei = perm_rank2edge[0];
  if (icp[ei] < 0) {
    return LightCompleteGraph::InvalidEdge;
  }
  NodeId u = std::ceil(std::sqrt(2*(ei+1)+0.25) - 0.5);
  NodeId v = ei - u * (u-1) / 2;
  return Edge(u, v);
}

EdgeWeight EdgeHeap::getIcf(const Edge e) const {
  return icf[e.id()];
}

EdgeWeight EdgeHeap::getIcp(const Edge e) const {
  return icp[e.id()];
}

void EdgeHeap::increaseIcf(const Edge e, const EdgeWeight w) {
  EdgeId id = e.id();
  if (w != 0 && icf[id] >= 0) {
    icf[id] += w;
    icf[id] = std::max(icf[id], 0.0);
    updateHeap(forb_rank2edge, id, w, edge2forb_rank, icf);
  }
}

void EdgeHeap::increaseIcp(const Edge e, const EdgeWeight w) {
  EdgeId id = e.id();
  if (w != 0 && icp[id] >= 0) {
    icp[id] += w;
    icp[id] = std::max(icp[id], 0.0);
    updateHeap(perm_rank2edge, id, w, edge2perm_rank, icp);
  }
}

void EdgeHeap::removeEdge(const Edge e) {
  EdgeId id = e.id();
  if (icf[id] != LightCompleteGraph::Forbidden && icp[id] != LightCompleteGraph::Forbidden) {
    icf[id] = LightCompleteGraph::Forbidden;
    icp[id] = LightCompleteGraph::Forbidden;
    updateHeap(forb_rank2edge, id, LightCompleteGraph::Forbidden, edge2forb_rank, icf);
    updateHeap(perm_rank2edge, id, LightCompleteGraph::Forbidden, edge2perm_rank, icp);
    unprocessed--;
  }
}

LightCompleteGraph::EdgeWeight EdgeHeap::getIcf(const EdgeWeight uw, const EdgeWeight vw) const {
  if (uw > 0 && vw > 0) {
    // if both other edges present, remove the cheapest of both
    return std::min(uw, vw);
  } else {
    return 0;
  }
}

LightCompleteGraph::EdgeWeight EdgeHeap::getIcp(const EdgeWeight uw, const EdgeWeight vw) const {
  if (uw < 0 && vw > 0) {
    return std::min(vw, -uw); 	// either add uw or remove vw
  } else if (uw > 0 && vw < 0) {
    return std::min(-vw, uw); 	// either add vw or remove uw
  } else {
    return 0;
  }
}

int EdgeHeap::numUnprocessed() const {
  return unprocessed;
}

void EdgeHeap::updateHeap(std::vector<EdgeId>& heap, const EdgeId e, const EdgeWeight change, std::vector<EdgeId>& index, const std::vector<EdgeWeight>& score) {
  unsigned int pos = index[e];
  if (change > 0) {
    // value increased -> move edge upwards in heap
    while(score[heap[pos/2]] < score[heap[pos]]) {
      // swap pos and pos/2
      std::swap(heap[pos], heap[pos/2]);
      index[heap[pos]] = pos;
      index[heap[pos/2]] = pos/2;
      pos = pos/2;
    }
  } else {
  // value decreased -> move edge downwards in heap
  while((2*pos < heap.size() && score[heap[pos]] < score[heap[2*pos]])
      || (2*pos+1 < heap.size() && score[heap[pos]] < score[heap[2*pos+1]]) ) {
    if (2*pos+1 < heap.size() && score[heap[2*pos]] < score[heap[2*pos+1]]) {
      // element 2*pos+1 exists and is larger than 2*pos -> swap pos with 2*pos+1
      std::swap(heap[pos], heap[2*pos+1]);
      index[heap[pos]] = pos;
      index[heap[pos*2+1]] = pos*2+1;
      pos = 2*pos+1;
    } else {
      // else swap with 2*pos
      std::swap(heap[pos], heap[2*pos]);
      index[heap[pos]] = pos;
      index[heap[pos*2]] = pos*2;
      pos = 2*pos;
    }
  }
}
//   bool wrong = false;
//   unsigned int where = 0;
//   for (unsigned int i = 0; i < heap.size()/2; i++) {
//     if (score[heap[i]] < score[heap[2*i]]) {
//       wrong = true;
//       where = i;
//     }
//     if (2*i+1 < heap.size() && score[heap[i]] < score[heap[2*i+1]]) {
//       wrong = true;
//       where = i;
//     }
//   }
//   if (wrong) {
//     std::cout<<"Error in heap ("<<where<<") "<<score[heap[where/2]]<<" >= "<<score[heap[where]]<<" >= "<<score[heap[2*where]]<<" & "<<score[heap[2*where+1]]<<std::endl;
//   }
}

} // namespace ysk<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <windows.h>
#endif
#if     qPlatform_POSIX && qSupport_Proc_Filesystem
#include    <unistd.h>
#endif

#include    "../Execution/ErrNoException.h"
#include    "../Execution/Exceptions.h"
#include    "../Memory/SmallStackBuffer.h"
#include    "../IO/FileSystem/PathName.h"

#include    "Module.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Execution;

/*
 ********************************************************************************
 ***************************** Execution::GetEXEDir *****************************
 ********************************************************************************
 */
String Execution::GetEXEDir ()
{
    return String::FromSDKString (GetEXEDirT ());
}

/*
 ********************************************************************************
 ***************************** Execution::GetEXEDirT *****************************
 ********************************************************************************
 */
SDKString Execution::GetEXEDirT ()
{
    // Currently this impl depends on String - we may want to redo one cleanly without any dependency on String()...
    // Docs call for this - but I'm not sure its needed
    return IO::FileSystem::GetFileDirectory (GetEXEPath ()).AsSDKString ();
}

/*
 ********************************************************************************
 **************************** Execution::GetEXEPath *****************************
 ********************************************************************************
 */
String Execution::GetEXEPath ()
{
    return String::FromSDKString (GetEXEPathT ());
}

/*
 ********************************************************************************
 **************************** Execution::GetEXEPathT ****************************
 ********************************************************************************
 */
SDKString Execution::GetEXEPathT ()
{
    // See also http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
    //      Mac OS X: _NSGetExecutablePath() (man 3 dyld)
    //      Linux: readlink /proc/self/exe
    //      Solaris: getexecname()
    //      FreeBSD: sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1
    //      BSD with procfs: readlink /proc/curproc/file
    //      Windows: GetModuleFileName() with hModule = nullptr
    //
#if     qPlatform_Windows
    Characters::SDKChar   buf[MAX_PATH];
    memset (buf, 0, sizeof (buf));
    Verify (::GetModuleFileName (nullptr, buf, NEltsOf (buf)));
    return buf;
#elif   qPlatform_POSIX && qSupport_Proc_Filesystem
    // readlink () isn't clear about finding the right size. THe only way to tell it wasn't enuf (maybe) is if all the
    // bytes passed in are used. That COULD mean it all fit, or there was more. If we get that - double buf size and try again
    Memory::SmallStackBuffer<Characters::SDKChar> buf (1000);
    ssize_t n;
    while ( (n = readlink ("/proc/self/exe", buf, buf.GetSize () - 1)) == buf.GetSize ()) {
        buf.GrowToSize (buf.GetSize () * 2);
    }
    if (n < 0) {
        errno_ErrorException::DoThrow (errno);
    }
    Assert (n < buf.GetSize ());
    *(buf.begin () + n) = '\0';
    return buf.begin ();
#else
    AssertNotImplemented ();
    return SDKString ();
#endif
}

<commit_msg>cleanup memset / readlink usag ein Execution::GetEXEPathT ()<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <windows.h>
#endif
#if     qPlatform_POSIX && qSupport_Proc_Filesystem
#include    <unistd.h>
#endif

#include    "../Execution/ErrNoException.h"
#include    "../Execution/Exceptions.h"
#include    "../Memory/SmallStackBuffer.h"
#include    "../IO/FileSystem/PathName.h"

#include    "Module.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Execution;

/*
 ********************************************************************************
 ***************************** Execution::GetEXEDir *****************************
 ********************************************************************************
 */
String Execution::GetEXEDir ()
{
    return String::FromSDKString (GetEXEDirT ());
}

/*
 ********************************************************************************
 ***************************** Execution::GetEXEDirT *****************************
 ********************************************************************************
 */
SDKString Execution::GetEXEDirT ()
{
    // Currently this impl depends on String - we may want to redo one cleanly without any dependency on String()...
    // Docs call for this - but I'm not sure its needed
    return IO::FileSystem::GetFileDirectory (GetEXEPath ()).AsSDKString ();
}

/*
 ********************************************************************************
 **************************** Execution::GetEXEPath *****************************
 ********************************************************************************
 */
String Execution::GetEXEPath ()
{
    return String::FromSDKString (GetEXEPathT ());
}

/*
 ********************************************************************************
 **************************** Execution::GetEXEPathT ****************************
 ********************************************************************************
 */
SDKString Execution::GetEXEPathT ()
{
    // See also http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
    //      Mac OS X: _NSGetExecutablePath() (man 3 dyld)
    //      Linux: readlink /proc/self/exe
    //      Solaris: getexecname()
    //      FreeBSD: sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1
    //      BSD with procfs: readlink /proc/curproc/file
    //      Windows: GetModuleFileName() with hModule = nullptr
    //
#if     qPlatform_Windows
    Characters::SDKChar   buf[MAX_PATH];
    //memset (buf, 0, sizeof (buf));
    Verify (::GetModuleFileName (nullptr, buf, NEltsOf (buf)));
    buf[NEltsOf (buf) - 1] = '\0';  // cheaper and just as safe as memset() - more even. Buffer always nul-terminated, and if GetModuleFileName succeeds will be nul-terminated
    return buf;
#elif   qPlatform_POSIX && qSupport_Proc_Filesystem
    // readlink () isn't clear about finding the right size. THe only way to tell it wasn't enuf (maybe) is if all the
    // bytes passed in are used. That COULD mean it all fit, or there was more. If we get that - double buf size and try again
    Memory::SmallStackBuffer<Characters::SDKChar> buf (1000);
    ssize_t n;
    while ( (n = readlink ("/proc/self/exe", buf, buf.GetSize ())) == buf.GetSize ()) {
        buf.GrowToSize (buf.GetSize () * 2);
    }
    if (n < 0) {
        errno_ErrorException::DoThrow (errno);
    }
    Assert (n <= buf.GetSize ());   // could leave no room for NUL-byte, but not needed
    return SDKString (buf.begin (), buf.begin () + n);
#else
    AssertNotImplemented ();
    return SDKString ();
#endif
}

<|endoftext|>