<commit_before>/*
 * This file is part of the Camera Streaming Daemon
 *
 * Copyright (C) 2017  Intel Corporation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <assert.h>
#include <mavlink.h>
#include <sys/socket.h>
#include <unistd.h>

#include "log.h"
#include "mainloop.h"
#include "mavlink_server.h"

#define DEFAULT_MAVLINK_PORT 14550
#define DEFAULT_MAVLINK_BROADCAST_ADDR "255.255.255.255"

MavlinkServer::MavlinkServer(std::vector<std::unique_ptr<Stream>> &streams)
    : _streams(streams)
    , _is_running(false)
    , _timeout_handler(0)
{
}

MavlinkServer::~MavlinkServer()
{
    stop();
}

void MavlinkServer::_handle_camera_info_request(unsigned int camera_id)
{
    uint8_t buffer[1024];
    struct buffer buf = {0, buffer};
    mavlink_message_t msg;

    log_debug("camera id %d", camera_id);
    for (auto const &s : _streams) {
        if (camera_id == 0 || camera_id == s->id) {
            mavlink_msg_camera_information_pack(
                _get_system_id(), MAV_COMP_ID_CAMERA, &msg, 0, s->id, 1,
                (const uint8_t *)s->get_name().c_str() /* TODO: Get vendor name. */,
                (const uint8_t *)s->get_name().c_str(), 0, 0, 0, 0, 0, 0, 0);
        }

        buf.len = mavlink_msg_to_send_buffer(buf.data, &msg);
        if (!buf.len || _udp.write(buf) < 0) {
            log_error("Sending camera information failed for camera %d.", s->id);
            return;
        }
    }
}

void MavlinkServer::_handle_mavlink_message(mavlink_message_t *msg)
{
    log_debug("Message received: (sysid: %d compid: %d msgid: %d)", msg->sysid, msg->compid,
              msg->msgid);

    if (msg->msgid == MAVLINK_MSG_ID_COMMAND_LONG) {
        mavlink_command_long_t cmd;
        mavlink_msg_command_long_decode(msg, &cmd);

        if (cmd.target_system != _get_system_id() || cmd.target_component != MAV_COMP_ID_CAMERA)
            return;

        switch (cmd.command) {
        case MAV_CMD_REQUEST_CAMERA_INFORMATION:
            this->_handle_camera_info_request(cmd.param2 /* Camera ID */);
            break;
        default:
            log_debug("Command %d unhandled. Discarding.", cmd.command);
        }
    }
}

void MavlinkServer::_message_received(const struct buffer &buf)
{
    mavlink_message_t msg;
    mavlink_status_t status;

    for (unsigned int i = 0; i < buf.len; ++i) {
        //TOOD: Parse mavlink message all at once, instead of using mavlink_parse_char
        if (mavlink_parse_char(MAVLINK_COMM_0, buf.data[i], &msg, &status))
            _handle_mavlink_message(&msg);
    }
}

bool _heartbeat_cb(void *data)
{
    assert(data);
    uint8_t buffer[1024];
    struct buffer buf = {0, buffer};

    MavlinkServer *server = (MavlinkServer *)data;
    mavlink_message_t msg;

    mavlink_msg_heartbeat_pack(1, MAV_COMP_ID_CAMERA, &msg, MAV_TYPE_GENERIC, MAV_AUTOPILOT_INVALID,
                               MAV_MODE_PREFLIGHT, 0, MAV_STATE_ACTIVE);
    // TODO: pack this in one function. Maybe in a class called MAVLinkSocket.
    buf.len = mavlink_msg_to_send_buffer(buf.data, &msg);
    if (!buf.len || server->_udp.write(buf) < 0)
        log_error("Sending HEARTBEAT failed.");
    else
        log_debug("HEARTBEAT");

    return true;
}

void MavlinkServer::start()
{
    if (_is_running)
        return;
    _is_running = true;

    _udp.open(DEFAULT_MAVLINK_BROADCAST_ADDR, DEFAULT_MAVLINK_PORT, false);
    _udp.set_read_callback([this](const struct buffer &buf) { this->_message_received(buf); });
    _timeout_handler = Mainloop::get_mainloop()->add_timeout(1000, _heartbeat_cb, this);
}

void MavlinkServer::stop()
{
    if (!_is_running)
        return;
    _is_running = false;

    if (_timeout_handler > 0)
        Mainloop::get_mainloop()->del_timeout(_timeout_handler);
}

int MavlinkServer::_get_system_id()
{
    return 1;
}
<commit_msg>mavlink: Send empty vendor instead of duplicating the camera name<commit_after>/*
 * This file is part of the Camera Streaming Daemon
 *
 * Copyright (C) 2017  Intel Corporation. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <assert.h>
#include <mavlink.h>
#include <sys/socket.h>
#include <unistd.h>

#include "log.h"
#include "mainloop.h"
#include "mavlink_server.h"

#define DEFAULT_MAVLINK_PORT 14550
#define DEFAULT_MAVLINK_BROADCAST_ADDR "255.255.255.255"

MavlinkServer::MavlinkServer(std::vector<std::unique_ptr<Stream>> &streams)
    : _streams(streams)
    , _is_running(false)
    , _timeout_handler(0)
{
}

MavlinkServer::~MavlinkServer()
{
    stop();
}

void MavlinkServer::_handle_camera_info_request(unsigned int camera_id)
{
    uint8_t buffer[1024];
    struct buffer buf = {0, buffer};
    mavlink_message_t msg;

    log_debug("camera id %d", camera_id);
    for (auto const &s : _streams) {
        if (camera_id == 0 || camera_id == s->id) {
            mavlink_msg_camera_information_pack(
                _get_system_id(), MAV_COMP_ID_CAMERA, &msg, 0, s->id, 1,
                (const uint8_t *)"",
                (const uint8_t *)s->get_name().c_str(), 0, 0, 0, 0, 0, 0, 0);
        }

        buf.len = mavlink_msg_to_send_buffer(buf.data, &msg);
        if (!buf.len || _udp.write(buf) < 0) {
            log_error("Sending camera information failed for camera %d.", s->id);
            return;
        }
    }
}

void MavlinkServer::_handle_mavlink_message(mavlink_message_t *msg)
{
    log_debug("Message received: (sysid: %d compid: %d msgid: %d)", msg->sysid, msg->compid,
              msg->msgid);

    if (msg->msgid == MAVLINK_MSG_ID_COMMAND_LONG) {
        mavlink_command_long_t cmd;
        mavlink_msg_command_long_decode(msg, &cmd);

        if (cmd.target_system != _get_system_id() || cmd.target_component != MAV_COMP_ID_CAMERA)
            return;

        switch (cmd.command) {
        case MAV_CMD_REQUEST_CAMERA_INFORMATION:
            this->_handle_camera_info_request(cmd.param2 /* Camera ID */);
            break;
        default:
            log_debug("Command %d unhandled. Discarding.", cmd.command);
        }
    }
}

void MavlinkServer::_message_received(const struct buffer &buf)
{
    mavlink_message_t msg;
    mavlink_status_t status;

    for (unsigned int i = 0; i < buf.len; ++i) {
        //TOOD: Parse mavlink message all at once, instead of using mavlink_parse_char
        if (mavlink_parse_char(MAVLINK_COMM_0, buf.data[i], &msg, &status))
            _handle_mavlink_message(&msg);
    }
}

bool _heartbeat_cb(void *data)
{
    assert(data);
    uint8_t buffer[1024];
    struct buffer buf = {0, buffer};

    MavlinkServer *server = (MavlinkServer *)data;
    mavlink_message_t msg;

    mavlink_msg_heartbeat_pack(1, MAV_COMP_ID_CAMERA, &msg, MAV_TYPE_GENERIC, MAV_AUTOPILOT_INVALID,
                               MAV_MODE_PREFLIGHT, 0, MAV_STATE_ACTIVE);
    // TODO: pack this in one function. Maybe in a class called MAVLinkSocket.
    buf.len = mavlink_msg_to_send_buffer(buf.data, &msg);
    if (!buf.len || server->_udp.write(buf) < 0)
        log_error("Sending HEARTBEAT failed.");
    else
        log_debug("HEARTBEAT");

    return true;
}

void MavlinkServer::start()
{
    if (_is_running)
        return;
    _is_running = true;

    _udp.open(DEFAULT_MAVLINK_BROADCAST_ADDR, DEFAULT_MAVLINK_PORT, false);
    _udp.set_read_callback([this](const struct buffer &buf) { this->_message_received(buf); });
    _timeout_handler = Mainloop::get_mainloop()->add_timeout(1000, _heartbeat_cb, this);
}

void MavlinkServer::stop()
{
    if (!_is_running)
        return;
    _is_running = false;

    if (_timeout_handler > 0)
        Mainloop::get_mainloop()->del_timeout(_timeout_handler);
}

int MavlinkServer::_get_system_id()
{
    return 1;
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkPlatonicSolidSource.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/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 notice for more information.

=========================================================================*/
#include "vtkPlatonicSolidSource.h"

#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkPoints.h"

vtkCxxRevisionMacro(vtkPlatonicSolidSource, "1.4");
vtkStandardNewMacro(vtkPlatonicSolidSource);

// The geometry and topology of each solid. Solids are centered at
// the origin with radius 1.0.
// The golden ration phi = (1+sqrt(5))/2=1.61803398875 enters into many
// of these values.
static double TetraPoints[] = {
  1.0,1.0,1.0, -1.0,1.0,-1.0, 1.0,-1.0,-1.0, -1.0,-1.0,1.0
};
static vtkIdType TetraVerts[] = {
  0,1,2, 1,3,2, 0,2,3, 0,3,1
};

static double CubePoints[] = {
  -1.0,-1.0,-1.0, 1.0,-1.0,-1.0, 1.0,1.0,-1.0, -1.0,1.0,-1.0,
  -1.0,-1.0,1.0, 1.0,-1.0,1.0, 1.0,1.0,1.0, -1.0,1.0,1.0
};
static vtkIdType CubeVerts[] = {
  0,1,5,4, 0,4,7,3, 4,5,6,7, 3,7,6,2, 1,2,6,5, 0,3,2,1
};

static double OctPoints[] = {
  -1.0,-1.0,0.0, 1.0,-1.0,0.0, 1.0,1.0,0.0, -1.0,1.0,0.0,
  0.0,0.0,-1.4142135623731, 0.0,0.0,1.4142135623731
};
static vtkIdType OctVerts[] = {
  4,1,0, 4,2,1, 4,3,2, 4,0,3, 0,1,5, 1,2,5, 2,3,5, 3,0,5
};

static double a = 0.61803398875;
static double b = 0.381966011250;
static double DodePoints[] = {
   b, 0, 1,  -b, 0, 1,  b, 0,-1, -b, 0,-1,  0, 1,-b,
   0, 1, b,   0,-1,-b,  0,-1, b,  1, b, 0,  1,-b, 0,
  -1, b, 0,  -1,-b, 0, -a, a, a,  a,-a, a, -a,-a,-a,
   a, a,-a,   a, a, a, -a, a,-a, -a,-a, a,  a,-a,-a
};
static vtkIdType DodeVerts[] = {
  0,1,12,5,16, 1,0,13,7,18, 2,3,14,6,19, 3,2,15,4,17, 4,5,16,8,15,
  5,4,17,10,12, 6,7,18,11,14, 7,6,19,9,13, 8,9,13,0,16, 9,8,15,2,19,
  10,11,14,3,17, 11,10,12,1,18
};

static double c = 0.5;
static double d = 0.30901699;
static double IcosaPoints[] = {
   0.0,d,-c, 0.0,d,c,  0.0,-d,c, -d,c,0.0,
  -d,-c,0.0, d,c,0.0,  d,-c,0.0,  0.0,-d,-c,
   c,0.0,d, -c,0.0,d, -c,0.0,-d,  c,0.0,-d
};
static vtkIdType IcosaVerts[] = {
  0,5,3, 1,3,5, 1,2,9, 1,8,2, 0,7,11, 0,10,7, 2,6,4, 7,4,6, 3,9,10,
  4,10,9, 5,11,8, 6,8,11, 1,9,3, 1,5,8, 0,3,10, 0,11,5, 7,10,4, 7,6,11,
  2,4,9, 2,8,6
};

vtkPlatonicSolidSource::vtkPlatonicSolidSource()
{
  this->SolidType = VTK_SOLID_TETRAHEDRON;
  this->SetNumberOfInputPorts(0);
}

int vtkPlatonicSolidSource::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **vtkNotUsed(inputVector),
  vtkInformationVector *outputVector)
{
  // get the info object
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // get the ouptut
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  int i;
  double *pptr, *solidPoints=NULL, solidScale=1.0;
  vtkIdType *cptr, numPts=0, numCells=0, cellSize=0, *solidVerts=NULL;

  vtkDebugMacro(<<"Creating Platonic solid");

  // Based on type, select correct connectivity and point arrays
  //
  switch (this->SolidType)
    {
    case VTK_SOLID_TETRAHEDRON:
      numPts = 4;
      cellSize = 3;
      numCells = 4;
      solidPoints = TetraPoints;
      solidVerts = TetraVerts;
      solidScale = 1.0/sqrt(3.0);
      break;

    case VTK_SOLID_CUBE:
      numPts = 8;
      cellSize = 4;
      numCells = 6;
      solidPoints = CubePoints;
      solidVerts = CubeVerts;
      solidScale = 1.0/sqrt(3.0);
      break;

    case VTK_SOLID_OCTAHEDRON:
      numPts = 6;
      cellSize = 3;
      numCells = 8;
      solidPoints = OctPoints;
      solidVerts = OctVerts;
      solidScale = 1.0/sqrt(2.0);
      break;

    case VTK_SOLID_ICOSAHEDRON:
      numPts = 12;
      cellSize = 3;
      numCells = 20;
      solidPoints = IcosaPoints;
      solidVerts = IcosaVerts;
      solidScale = 1.0/0.58778524999243;
      break;

    case VTK_SOLID_DODECAHEDRON:
      numPts = 20;
      cellSize = 5;
      numCells = 12;
      solidPoints = DodePoints;
      solidVerts = DodeVerts;
      solidScale = 1.0/1.070466269319;
      break;
    }

  // Create the solids
  //
  vtkPoints *pts = vtkPoints::New();
  pts->SetDataTypeToDouble();
  pts->SetNumberOfPoints(numPts);
  vtkCellArray *polys = vtkCellArray::New();
  polys->Allocate(polys->EstimateSize(numCells,cellSize));
  vtkIntArray *colors = vtkIntArray::New();
  colors->SetNumberOfComponents(1);
  colors->SetNumberOfTuples(numCells);

  // Points
  for ( i=0, pptr=solidPoints; i<numPts; i++, pptr+=3 )
    {
    pts->SetPoint(i, solidScale*(pptr[0]), solidScale*(pptr[1]),
                     solidScale*(pptr[2]));
    }

  // Cells
  for ( i=0, cptr=solidVerts; i<numCells; i++, cptr+=cellSize )
    {
    polys->InsertNextCell(cellSize,cptr);
    colors->SetTuple1(i,i);
    }

  // Assemble the output
  output->SetPoints(pts);
  output->SetPolys(polys);
  int idx = output->GetCellData()->AddArray(colors);
  output->GetCellData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);

  pts->Delete();
  polys->Delete();
  colors->Delete();

  return 1;
}

void vtkPlatonicSolidSource::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Solid Type: " << "\n";
  if ( this->SolidType == VTK_SOLID_TETRAHEDRON )
    {
    os << "Tetrahedron\n";
    }
  else if ( this->SolidType == VTK_SOLID_CUBE )
    {
    os << "Cube\n";
    }
  else if ( this->SolidType == VTK_SOLID_OCTAHEDRON )
    {
    os << "Octahedron\n";
    }
  else if ( this->SolidType == VTK_SOLID_ICOSAHEDRON )
    {
    os << "Icosahedron\n";
    }
  else //if ( this->SolidType == VTK_SOLID_DODECAHEDRON )
    {
    os << "Dodecahedron\n";
    }
}
<commit_msg>BUG: faces of dodecahedron were flipped<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPlatonicSolidSource.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/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 notice for more information.

=========================================================================*/
#include "vtkPlatonicSolidSource.h"

#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkPoints.h"

vtkCxxRevisionMacro(vtkPlatonicSolidSource, "1.5");
vtkStandardNewMacro(vtkPlatonicSolidSource);

// The geometry and topology of each solid. Solids are centered at
// the origin with radius 1.0.
// The golden ration phi = (1+sqrt(5))/2=1.61803398875 enters into many
// of these values.
static double TetraPoints[] = {
  1.0,1.0,1.0, -1.0,1.0,-1.0, 1.0,-1.0,-1.0, -1.0,-1.0,1.0
};
static vtkIdType TetraVerts[] = {
  0,1,2, 1,3,2, 0,2,3, 0,3,1
};

static double CubePoints[] = {
  -1.0,-1.0,-1.0, 1.0,-1.0,-1.0, 1.0,1.0,-1.0, -1.0,1.0,-1.0,
  -1.0,-1.0,1.0, 1.0,-1.0,1.0, 1.0,1.0,1.0, -1.0,1.0,1.0
};
static vtkIdType CubeVerts[] = {
  0,1,5,4, 0,4,7,3, 4,5,6,7, 3,7,6,2, 1,2,6,5, 0,3,2,1
};

static double OctPoints[] = {
  -1.0,-1.0,0.0, 1.0,-1.0,0.0, 1.0,1.0,0.0, -1.0,1.0,0.0,
  0.0,0.0,-1.4142135623731, 0.0,0.0,1.4142135623731
};
static vtkIdType OctVerts[] = {
  4,1,0, 4,2,1, 4,3,2, 4,0,3, 0,1,5, 1,2,5, 2,3,5, 3,0,5
};

static double a = 0.61803398875;
static double b = 0.381966011250;
static double DodePoints[] = {
   b, 0, 1,  -b, 0, 1,  b, 0,-1, -b, 0,-1,  0, 1,-b,
   0, 1, b,   0,-1,-b,  0,-1, b,  1, b, 0,  1,-b, 0,
  -1, b, 0,  -1,-b, 0, -a, a, a,  a,-a, a, -a,-a,-a,
   a, a,-a,   a, a, a, -a, a,-a, -a,-a, a,  a,-a,-a
};
static vtkIdType DodeVerts[] = {
  0,16,5,12,1, 1,18,7,13,0, 2,19,6,14,3, 3,17,4,15,2, 4,5,16,8,15,
  5,4,17,10,12, 6,7,18,11,14, 7,6,19,9,13, 8,16,0,13,9, 9,19,2,15,8,
  10,17,3,14,11, 11,18,1,12,10
};

static double c = 0.5;
static double d = 0.30901699;
static double IcosaPoints[] = {
   0.0,d,-c, 0.0,d,c,  0.0,-d,c, -d,c,0.0,
  -d,-c,0.0, d,c,0.0,  d,-c,0.0,  0.0,-d,-c,
   c,0.0,d, -c,0.0,d, -c,0.0,-d,  c,0.0,-d
};
static vtkIdType IcosaVerts[] = {
  0,5,3, 1,3,5, 1,2,9, 1,8,2, 0,7,11, 0,10,7, 2,6,4, 7,4,6, 3,9,10,
  4,10,9, 5,11,8, 6,8,11, 1,9,3, 1,5,8, 0,3,10, 0,11,5, 7,10,4, 7,6,11,
  2,4,9, 2,8,6
};

vtkPlatonicSolidSource::vtkPlatonicSolidSource()
{
  this->SolidType = VTK_SOLID_TETRAHEDRON;
  this->SetNumberOfInputPorts(0);
}

int vtkPlatonicSolidSource::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **vtkNotUsed(inputVector),
  vtkInformationVector *outputVector)
{
  // get the info object
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  // get the ouptut
  vtkPolyData *output = vtkPolyData::SafeDownCast(
    outInfo->Get(vtkDataObject::DATA_OBJECT()));

  int i;
  double *pptr, *solidPoints=NULL, solidScale=1.0;
  vtkIdType *cptr, numPts=0, numCells=0, cellSize=0, *solidVerts=NULL;

  vtkDebugMacro(<<"Creating Platonic solid");

  // Based on type, select correct connectivity and point arrays
  //
  switch (this->SolidType)
    {
    case VTK_SOLID_TETRAHEDRON:
      numPts = 4;
      cellSize = 3;
      numCells = 4;
      solidPoints = TetraPoints;
      solidVerts = TetraVerts;
      solidScale = 1.0/sqrt(3.0);
      break;

    case VTK_SOLID_CUBE:
      numPts = 8;
      cellSize = 4;
      numCells = 6;
      solidPoints = CubePoints;
      solidVerts = CubeVerts;
      solidScale = 1.0/sqrt(3.0);
      break;

    case VTK_SOLID_OCTAHEDRON:
      numPts = 6;
      cellSize = 3;
      numCells = 8;
      solidPoints = OctPoints;
      solidVerts = OctVerts;
      solidScale = 1.0/sqrt(2.0);
      break;

    case VTK_SOLID_ICOSAHEDRON:
      numPts = 12;
      cellSize = 3;
      numCells = 20;
      solidPoints = IcosaPoints;
      solidVerts = IcosaVerts;
      solidScale = 1.0/0.58778524999243;
      break;

    case VTK_SOLID_DODECAHEDRON:
      numPts = 20;
      cellSize = 5;
      numCells = 12;
      solidPoints = DodePoints;
      solidVerts = DodeVerts;
      solidScale = 1.0/1.070466269319;
      break;
    }

  // Create the solids
  //
  vtkPoints *pts = vtkPoints::New();
  pts->SetDataTypeToDouble();
  pts->SetNumberOfPoints(numPts);
  vtkCellArray *polys = vtkCellArray::New();
  polys->Allocate(polys->EstimateSize(numCells,cellSize));
  vtkIntArray *colors = vtkIntArray::New();
  colors->SetNumberOfComponents(1);
  colors->SetNumberOfTuples(numCells);

  // Points
  for ( i=0, pptr=solidPoints; i<numPts; i++, pptr+=3 )
    {
    pts->SetPoint(i, solidScale*(pptr[0]), solidScale*(pptr[1]),
                     solidScale*(pptr[2]));
    }

  // Cells
  for ( i=0, cptr=solidVerts; i<numCells; i++, cptr+=cellSize )
    {
    polys->InsertNextCell(cellSize,cptr);
    colors->SetTuple1(i,i);
    }

  // Assemble the output
  output->SetPoints(pts);
  output->SetPolys(polys);
  int idx = output->GetCellData()->AddArray(colors);
  output->GetCellData()->SetActiveAttribute(idx, vtkDataSetAttributes::SCALARS);

  pts->Delete();
  polys->Delete();
  colors->Delete();

  return 1;
}

void vtkPlatonicSolidSource::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Solid Type: " << "\n";
  if ( this->SolidType == VTK_SOLID_TETRAHEDRON )
    {
    os << "Tetrahedron\n";
    }
  else if ( this->SolidType == VTK_SOLID_CUBE )
    {
    os << "Cube\n";
    }
  else if ( this->SolidType == VTK_SOLID_OCTAHEDRON )
    {
    os << "Octahedron\n";
    }
  else if ( this->SolidType == VTK_SOLID_ICOSAHEDRON )
    {
    os << "Icosahedron\n";
    }
  else //if ( this->SolidType == VTK_SOLID_DODECAHEDRON )
    {
    os << "Dodecahedron\n";
    }
}
<|endoftext|>


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

#include <iostream>
#include <string>
#include <vector>
#include "ui.hpp"

using namespace std;

namespace magicSearchEngine {

    std::pair<cmd, vector<string>>
    console::get_cmd() {
        string input;
        vector<string> opts;
        getline(is, input);
        if (is.eof())
            return make_pair(cmd::end_of_input, opts);
        if (is.fail())
            return make_pair(cmd::error, opts);
        if (input == "exit" || input == "quit" || input == "q")
            return make_pair(cmd::exit, opts);
        opts = parse_line(input);
        if (opts.size() == 0)
            return make_pair(cmd::parse_error, opts);
        if (opts[0] == "find")
            return make_pair(cmd::find, opts);

        return make_pair(cmd::none, opts);
    }

    vector<string>
    console::parse_line(const string & line) {
        vector<string> tokens;
        size_t line_length = line.length();
        bool double_quote = false;
        bool simple_quote = false;
        int token_length;
        for (int i = 0; i < line_length; i++) {
            int start = i;
            if (line[i] == '\"') {
                double_quote = true;
            }
            else if (line[i] == '\'') simple_quote = true;

            if (double_quote) {
                i++;
                start++;
                while (i < line_length && line[i] != '\"')
                    i++;
                if (i < line_length)
                    double_quote = false;
                token_length = i - start;
                i++;
            }
            else if (simple_quote) {
                i++;
                while (i < line_length && line[i] != '\'')
                    i++;
                if (i < line_length)
                    simple_quote = false;
                token_length = i - start;
                i++;
            }
            else {
                while (i < line_length && line[i] != ' ')
                    i++;
                token_length = i - start;
            }
            tokens.push_back(line.substr(start, token_length));
        }
        if (double_quote || simple_quote) {
            cout << "One of the quotes is open." << endl;
            return vector<string>();
        }
        return move(tokens);
    }
}<commit_msg>[src/ui.cpp] Warnings solved.<commit_after>/*
 * MIT License
 *
 * Copyright (c) 2017 Thomas Kremel
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <iostream>
#include <string>
#include <vector>
#include "ui.hpp"

using namespace std;

namespace magicSearchEngine {

    std::pair<cmd, vector<string>>
    console::get_cmd() {
        string input;
        vector<string> opts;
        getline(is, input);
        if (is.eof())
            return make_pair(cmd::end_of_input, opts);
        if (is.fail())
            return make_pair(cmd::error, opts);
        if (input == "exit" || input == "quit" || input == "q")
            return make_pair(cmd::exit, opts);
        opts = parse_line(input);
        if (opts.size() == 0)
            return make_pair(cmd::parse_error, opts);
        if (opts[0] == "find")
            return make_pair(cmd::find, opts);

        return make_pair(cmd::none, opts);
    }

    vector<string>
    console::parse_line(const string & line) {
        vector<string> tokens;
        size_t line_length = line.length();
        bool double_quote = false;
        bool simple_quote = false;
        size_t token_length;
        char dq_letter = '\"';
        char sq_letter = '\'';
        char s_letter = ' ';
        for (size_t i = 0; i < line_length; i++) {
            size_t start = i;
            if (line[i] == dq_letter) {
                double_quote = true;
            }
            else if (line[i] == sq_letter) simple_quote = true;

            if (double_quote) {
                i++;
                start++;
                while (i < line_length && line[i] != dq_letter)
                    i++;
                if (i < line_length)
                    double_quote = false;
                token_length = i - start;
                i++;
            }
            else if (simple_quote) {
                i++;
                while (i < line_length && line[i] != sq_letter)
                    i++;
                if (i < line_length)
                    simple_quote = false;
                token_length = i - start;
                i++;
            }
            else {
                while (i < line_length && line[i] != s_letter)
                    i++;
                token_length = i - start;
            }
            tokens.push_back(line.substr(start, token_length));
        }
        if (double_quote || simple_quote) {
            cout << "One of the quotes is open." << endl;
            return vector<string>();
        }
        return move(tokens);
    }
}<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <functional>
#include <fstream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>

#include "MatVec.h"
#include "Kugel.h"
#include "Box.h"

#include "auswertung_bsp_average_vel.h"
#include "auswertung_bsp_average_energy.h"
#include "PairDistribution.h"
#include <memory>
#include "AuswertVec.h"

using namespace std;

bool is_number(const string &str) {
	return str.find_first_not_of(".eE-0123456789") == string::npos;
}

int main(int argc, char* argv[]) {

	const unsigned DIM {3};

	//default Parameter: Dichte, Kugelanzahl, Kugelradius, Masse, Zeit runs, Zeit Warmlauf, Zeit Auswertung, Histogrammbreite
	double a_para[] {0.2, 108, 1.0, 1.0, 1E3, 1E2, 1E-1, 1E-1};
	int a_para_size = sizeof(a_para) / sizeof(*a_para);
	int i_para {1};

	for (i_para = 1; i_para < min(a_para_size + 1, argc); i_para++) {
		if (is_number(argv[i_para])) a_para[i_para - 1] = stod(argv[i_para]);
		else break;
	}

 //TODO: kann abhängig von Eingabe sein
	dimlessT density {a_para[0]};
	unsigned N {(unsigned)a_para[1]};
	lengthT radius {a_para[2]*m};
	massT mass {a_para[3]*kg};
	timeT simulation_time {a_para[4]*s};
	timeT warm_time {a_para[5]*s};
	timeT ausw_t_step {a_para[6]*s};
	double histo_width {a_para[7]};

	lengthT box_length {ceil(2.*radius*Pow(double(N)/density, 1, 3))*m};
	density = N*pow(radius*2./box_length, 3);

	cout << "Dimension:\t" << DIM << endl;
	cout << "Density:\t" << density << endl;
	cout << "Number of Spheres:\t" << N << endl;
	cout << "Boxlänge:\t" << box_length << endl;
	cout << "Radius:\t" << radius << endl;
	cout << "Warmlauf:\t" << warm_time << endl;
	cout << "Gesamte Simulationszeit:\t" << simulation_time + warm_time << endl;
	cout << "Auswertung alle\t" << ausw_t_step << endl;
	cout << "Histogrammgenauigkeit:\t" << histo_width << endl;

	AuswertVec<Kugel<DIM>> vec_unary;
	AuswertVec<Kugel<DIM>,Kugel<DIM>> vec_binary;

	MatVec<lengthT,DIM> box_size{box_length, box_length, box_length}; //TODO: kann abhängig von Eingabe sein
	Kugel<DIM> kugel1{mass, radius}; //TODO: kann abhängig von Eingabe sein
	MatVec<velocityT,DIM> vel{14};
	kugel1.velocity(vel);
	Box<DIM> box{box_size, N, kugel1}; //TODO: kann abhängig von Eingabe sein

	{//TODO: kann abhängig von Eingabe sein
		vec_unary.push_back( new auswertung_bsp_average_vel<DIM> );
		vec_unary.push_back( new auswertung_bsp_average_energy<DIM> );
		vec_binary.push_back(new PairDistribution<DIM> { histo_width, box_size });
	}

	ofstream dat_pair_dist;
	dat_pair_dist.open("pair_distribution.dat", ios::out | ios::trunc);
	const CollisionPair<DIM> &cp = box.collision_pair();
	unsigned count_no_coll { }, count_coll{ };

	if (! box.initiate()) {
		cout << "Zu viele Kugeln für Box.";
		return 1;
	}

/*	cout << "\nVor Warmlauf\n\n";
	box.print(cout);
	cout << '\n';

	box(vec_unary,vec_binary);
	vec_unary.print_result(cout);
	cout << '\n' << "vec_binary: ";
	vec_binary.print_result(cout);
*/

	timeT coll_time {};

	while (box.time() <= warm_time) {
		if (! cp) ++count_no_coll;
		coll_time = box.collide();
//		cout << coll_time << '\n';
		++count_coll;
	}
/*
	cout << "\nNach Warmlauf\n\n";
	box.print(cout);
	cout << '\n';
*/
	timeT ausw_t_next{ausw_t_step};

	cout << "Time: " << box.time() << '\n';
/*	box(vec_unary,vec_binary);
	vec_unary.print_result(cout);
	cout << '\n' << "vec_binary: ";
	vec_binary.print_result(cout);
*/
	//TODO: kann abhängig von Eingabe sein
	timeT simulation_end{simulation_time + box.time()};
	while (box.time() <= simulation_end){
		while ( ausw_t_next < box.next_event() ) {
			box.fast_forward(ausw_t_next);
			ausw_t_next = ausw_t_step;
			box(vec_unary, vec_binary);
		}
		if (! cp) ++count_no_coll;
		ausw_t_next -= box.collide();
		++count_coll;
	}

	cout << "Time: " << box.time() << '\n';
	vec_unary.print_result(cout);
	cout << '\n' << "vec_binary: ";
	vec_binary.print_result(dat_pair_dist);

	cout << "\n no collision: " << count_no_coll;
	cout << " of " << count_coll << " collisions";
	cout << "  => " << count_no_coll * 100. / count_coll << "%\n";
}
<commit_msg>Ausgabeblock ans Ende der Initialisierung verschoben<commit_after>#include <iostream>
#include <vector>
#include <functional>
#include <fstream>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>

#include "MatVec.h"
#include "Kugel.h"
#include "Box.h"

#include "auswertung_bsp_average_vel.h"
#include "auswertung_bsp_average_energy.h"
#include "PairDistribution.h"
#include <memory>
#include "AuswertVec.h"

using namespace std;

bool is_number(const string &str) {
	return str.find_first_not_of(".eE-0123456789") == string::npos;
}

int main(int argc, char* argv[]) {

	const unsigned DIM {3};

	//default Parameter: Dichte, Kugelanzahl, Kugelradius, Masse, Zeit runs, Zeit Warmlauf, Zeit Auswertung, Histogrammbreite
	double a_para[] {0.2, 108, 1.0, 1.0, 1E3, 1E2, 1E-1, 1E-1};
	int a_para_size = sizeof(a_para) / sizeof(*a_para);
	int i_para {1};

	for (i_para = 1; i_para < min(a_para_size + 1, argc); i_para++) {
		if (is_number(argv[i_para])) a_para[i_para - 1] = stod(argv[i_para]);
		else break;
	}

 //TODO: kann abhängig von Eingabe sein
	dimlessT density {a_para[0]};
	unsigned N {(unsigned)a_para[1]};
	lengthT radius {a_para[2]*m};
	massT mass {a_para[3]*kg};
	timeT simulation_time {a_para[4]*s};
	timeT warm_time {a_para[5]*s};
	timeT ausw_t_step {a_para[6]*s};
	double histo_width {a_para[7]};

	lengthT box_length {ceil(2.*radius*Pow(double(N)/density, 1, 3))*m};
	density = N*pow(radius*2./box_length, 3);

	AuswertVec<Kugel<DIM>> vec_unary;
	AuswertVec<Kugel<DIM>,Kugel<DIM>> vec_binary;

	MatVec<lengthT,DIM> box_size{box_length, box_length, box_length}; //TODO: kann abhängig von Eingabe sein
	Kugel<DIM> kugel1{mass, radius}; //TODO: kann abhängig von Eingabe sein
	MatVec<velocityT,DIM> vel{14};
	kugel1.velocity(vel);
	Box<DIM> box{box_size, N, kugel1}; //TODO: kann abhängig von Eingabe sein

	{//TODO: kann abhängig von Eingabe sein
		vec_unary.push_back( new auswertung_bsp_average_vel<DIM> );
		vec_unary.push_back( new auswertung_bsp_average_energy<DIM> );
		vec_binary.push_back(new PairDistribution<DIM> { histo_width, box_size });
	}

	ofstream dat_pair_dist;
	dat_pair_dist.open("pair_distribution.dat", ios::out | ios::trunc);
	const CollisionPair<DIM> &cp = box.collision_pair();
	unsigned count_no_coll { }, count_coll{ };

	cout << "Dimension:\t" << DIM << '\n';
	cout << "Density:\t" << density << '\n';
	cout << "Number of Spheres:\t" << N << '\n';
	cout << "Boxlänge:\t" << box_length << '\n';
	cout << "Radius:\t" << radius << '\n';
	cout << "Warmlauf:\t" << warm_time << '\n';
	cout << "Gesamte Simulationszeit:\t" << simulation_time + warm_time << '\n';
	cout << "Auswertung alle\t" << ausw_t_step << '\n';
	cout << "Histogrammgenauigkeit:\t" << histo_width << '\n';

	cout << "\n\nSTART SIMULATION\n" << endl;

	if (! box.initiate()) {
		cout << "Zu viele Kugeln für Box.";
		return 1;
	}

/*
	box.unitary(vec_unary);
	vec_unary.print_result(cout);
	cout << flush;
*/

/*	cout << "\nVor Warmlauf\n\n";
	box.print(cout);
	cout << '\n';

	box(vec_unary,vec_binary);
	vec_unary.print_result(cout);
	cout << '\n' << "vec_binary: ";
	vec_binary.print_result(cout);
*/

	timeT coll_time {};

	while (box.time() <= warm_time) {
		if (! cp) ++count_no_coll;
		coll_time = box.collide();
//		cout << coll_time << '\n';
		++count_coll;
	}
/*
	cout << "\nNach Warmlauf\n\n";
	box.print(cout);
	cout << '\n';
*/

	cout << "Time: " << box.time() << endl;
/*	box(vec_unary,vec_binary);
	vec_unary.print_result(cout);
	cout << '\n' << "vec_binary: ";
	vec_binary.print_result(cout);
*/
	//TODO: kann abhängig von Eingabe sein
	timeT ausw_t_next{ausw_t_step};
	timeT simulation_end{simulation_time + box.time()};
	while (box.time() <= simulation_end){
		while ( ausw_t_next < box.next_event() ) {
			box.fast_forward(ausw_t_next);
			ausw_t_next = ausw_t_step;
			box(vec_unary, vec_binary);
		}
		if (! cp) ++count_no_coll;
		ausw_t_next -= box.collide();
		++count_coll;
	}

	cout << "Time: " << box.time() << '\n';
	vec_unary.print_result(cout);
	cout << '\n' << "vec_binary: ";
	vec_binary.print_result(dat_pair_dist);

	cout << "\n no collision: " << count_no_coll;
	cout << " of " << count_coll << " collisions";
	cout << "  => " << count_no_coll * 100. / count_coll << "%\n";
}
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)
//
// Given string A representative a positive integer which has N digits,
// remove any k digits of the number, the remaining digits are arranged
// according to the original order to become a new positive integer.
// Make this new positive integers as small as possible.
//
// N <= 240 and k <= N,
//
// Example
// Given an integer A="178542", k=4
//
// return a string "12"
//

class Solution {
public:
    /**
     *@param A: A positive integer which has N digits, A is a string.
     *@param k: Remove k digits.
     *@return: A string
     */
    string DeleteDigits(string A, int k) {
        // If a digit is greater than next one, delete it.
        string s;
        for (const auto c : A) {
            while (k > 0 && !s.empty() && s.back() > c) {
                s.pop_back();
                --k;
            }
            s.push_back(c);
        }

        // If all digits are increasingly sorted, delete last.
        s.resize(s.length() - k);

        // Strip all leading '0'
        return s.empty() ? "0" : s.substr(s.find_first_not_of('0'));
    }
};

// Time:  O(k * n)
// Space: O(1)
// Greedy method
class Solution2 {
public:
    /**
     *@param A: A positive integer which has N digits, A is a string.
     *@param k: Remove k digits.
     *@return: A string
     */
    string DeleteDigits(string A, int k) {
        // If a digit is greater than next one, delete it.
        for (int i = 0; i + 1 <= A.size() && k > 0;) {
            if (A[i] > A[i + 1]) {
                A.erase(A.begin() + i); // Not efficient, linear time
                i = max(0, i - 1);
                --k;
            } else {
                ++i;
            }
        }

        // If all digits are increasingly sorted, delete last.
        A.resize(A.length() - k);

        // Strip all leading '0'
        return A.empty() ? "0" : A.substr(A.find_first_not_of('0'));
    }
};

<commit_msg>Update delete-digits.cpp<commit_after>// Time:  O(n)
// Space: O(n)
//
// Given string A representative a positive integer which has N digits,
// remove any k digits of the number, the remaining digits are arranged
// according to the original order to become a new positive integer.
// Make this new positive integers as small as possible.
//
// N <= 240 and k <= N,
//
// Example
// Given an integer A="178542", k=4
//
// return a string "12"
//

class Solution {
public:
    /**
     *@param A: A positive integer which has N digits, A is a string.
     *@param k: Remove k digits.
     *@return: A string
     */
    string DeleteDigits(string A, int k) {
        // If a digit is greater than next one, delete it.
        string s;
        for (const auto c : A) {
            while (k > 0 && !s.empty() && s.back() > c) {
                s.pop_back();
                --k;
            }
            s.push_back(c);
        }

        // If all digits are increasingly sorted, delete last.
        s.resize(s.length() - k);

        // Strip all leading '0'
        return s.empty() || s == "0" ? "0" : s.substr(s.find_first_not_of('0'));
    }
};

// Time:  O(k * n)
// Space: O(1)
// Greedy method
class Solution2 {
public:
    /**
     *@param A: A positive integer which has N digits, A is a string.
     *@param k: Remove k digits.
     *@return: A string
     */
    string DeleteDigits(string A, int k) {
        // If a digit is greater than next one, delete it.
        for (int i = 0; i + 1 <= A.size() && k > 0;) {
            if (A[i] > A[i + 1]) {
                A.erase(A.begin() + i); // Not efficient, linear time
                i = max(0, i - 1);
                --k;
            } else {
                ++i;
            }
        }

        // If all digits are increasingly sorted, delete last.
        A.resize(A.length() - k);

        // Strip all leading '0'
        return A.empty() || A == "0" ? "0" : A.substr(A.find_first_not_of('0'));
    }
};

<|endoftext|>


<commit_before>#ifndef UV_H
#define UV_H 1

#include <QString>
#include <map>

#include "structures.hpp"

//! Classe des UV
class Uv {

  public:

    Uv() {}

    //! Constructeur par défaut, met les ouvertures printemps et automne à false
    Uv(QString c, QString d) : code(c), description(d) {
        ouvertureAutomne = false;
        ouverturePrintemps = false;
    }

    inline const QString& getCode() const { return code; }
    inline const QString& getDescription() const { return description; }
    inline bool getOuvertureAutomne() const { return ouvertureAutomne; }
    inline bool getOuverturePrintemps() const { return ouverturePrintemps; }
    unsigned int getCredits() const;
    inline const std::map<QString, unsigned int>& getRecompenses() const { return recompenses; }

    inline void setCode(const QString &c) { code = c; }
    inline void setOuverturePrintemps(const bool &b) { ouverturePrintemps = b; }
    inline void setOuvertureAutomne(const bool &b) { ouvertureAutomne = b; }
    inline void setDescription(const QString &d) { description = d; }
    inline void setCredits(const QString &cat, const unsigned int &creds) { recompenses[cat] = creds; }
    inline bool operator==(const Uv& u) { return (u.getCode() == code); }

  private:
    QString code;
    QString description;
    std::map<QString, unsigned int> recompenses;
    bool ouvertureAutomne;
    bool ouverturePrintemps;

};

#endif // UV_H
<commit_msg>Modification de la gestion des crédits dans les UV<commit_after>#ifndef UV_H
#define UV_H 1

#include <QString>
#include <map>

#include "structures.hpp"

//! Classe des UV
class Uv {

  public:

    Uv() {}

    //! Constructeur par défaut, met les ouvertures printemps et automne à false
    Uv(QString c, QString d) : code(c), description(d) {
        ouvertureAutomne = false;
        ouverturePrintemps = false;
    }

    inline const QString& getCode() const { return code; }
    inline const QString& getDescription() const { return description; }
    inline bool getOuvertureAutomne() const { return ouvertureAutomne; }
    inline bool getOuverturePrintemps() const { return ouverturePrintemps; }
    unsigned int getCredits() const;
    inline const std::map<QString, unsigned int>& getRecompenses() const { return recompenses; }

    inline void setCode(const QString &c) { code = c; }
    inline void setOuverturePrintemps(const bool &b) { ouverturePrintemps = b; }
    inline void setOuvertureAutomne(const bool &b) { ouvertureAutomne = b; }
    inline void setDescription(const QString &d) { description = d; }
    inline void setCredits(const QString cat, const unsigned int creds) { recompenses[cat] = creds; }
    inline void resetCredits() { recompenses.clear(); }
    inline bool operator==(const Uv& u) { return (u.getCode() == code); }

  private:
    QString code;
    QString description;
    std::map<QString, unsigned int> recompenses;
    bool ouvertureAutomne;
    bool ouverturePrintemps;

};

#endif // UV_H
<|endoftext|>


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

#include "uwp.h"

std::thread::id NodeUtils::g_mainThreadId;
UWPAddOn UWPAddOn::s_instance;

bool UWPAddOn::EnsureCoInitialized() {
  if (!_coInitialized) {
    HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    _coInitialized = SUCCEEDED(hr);

    if (!_coInitialized) {
      NanThrowError("CoInitializeEx failed");
    }
  }

  return _coInitialized;
}

void UWPAddOn::EnsureCoUninitialized() {
  if (_coInitialized) {
    CoUninitialize();
    _coInitialized = false;
  }
}

bool UWPAddOn::EnsureKeepAlive() {
  if (_keepAliveToken == nullptr) {
    // Open an active async handler to keep Node alive
    _keepAliveToken = Async::GetAsyncToken();
  }

  return _keepAliveToken != nullptr;
}

void UWPAddOn::ReleaseKeepAlive() {
  if (_keepAliveToken != nullptr) {
    auto token = _keepAliveToken;
    _keepAliveToken = nullptr;

    Async::ReleaseAsyncToken(token);
  }
}

void UWPAddOn::Init(Handle<Object> target) {
  NanScope();

  NodeUtils::g_mainThreadId =
    std::this_thread::get_id();  // Capture entering thread id

  if (!s_instance.EnsureCoInitialized()) {
    return;
  }

  JsErrorCode err = JsSetProjectionEnqueueCallback(
    [](JsProjectionCallback jsCallback,
       JsProjectionCallbackContext jsContext, void *context) {
    Async::RunOnMain([jsCallback, jsContext]() {
      jsCallback(jsContext);
    });
  },
    /*projectionEnqueueContext*/nullptr);
  if (err != JsNoError) {
    NanThrowError("JsSetProjectionEnqueueCallback failed");
    return;
  }

  NODE_SET_METHOD(target, "projectNamespace", ProjectNamespace);
  NODE_SET_METHOD(target, "close", Close);
}

NAN_METHOD(UWPAddOn::ProjectNamespace) {
  NanScope();

  if (!args[0]->IsString()) {
    NanThrowError("Argument must be a string");
    NanReturnUndefined();
  }

  if (!s_instance.EnsureCoInitialized()) {
    NanReturnUndefined();
  }

  String::Value name(args[0]);
  if (JsProjectWinRTNamespace(reinterpret_cast<wchar_t*>(*name)) != JsNoError) {
    NanThrowError("JsProjectWinRTNamespace failed");
    NanReturnUndefined();
  }

  // Keep Node alive once successfully projected a UWP namespace
  s_instance.EnsureKeepAlive();
  NanReturnUndefined();
}

NAN_METHOD(UWPAddOn::Close) {
  NanScope();

  s_instance.ReleaseKeepAlive();
  s_instance.EnsureCoUninitialized();
  NanReturnUndefined();
}

NODE_MODULE(uwp, UWPAddOn::Init);
<commit_msg>Update to support nan 2.*<commit_after>// Copyright Microsoft. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and / or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "uwp.h"

std::thread::id NodeUtils::g_mainThreadId;
UWPAddOn UWPAddOn::s_instance;

bool UWPAddOn::EnsureCoInitialized() {
  if (!_coInitialized) {
    HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    _coInitialized = SUCCEEDED(hr);

    if (!_coInitialized) {
      Nan::ThrowError("CoInitializeEx failed");
    }
  }

  return _coInitialized;
}

void UWPAddOn::EnsureCoUninitialized() {
  if (_coInitialized) {
    CoUninitialize();
    _coInitialized = false;
  }
}

bool UWPAddOn::EnsureKeepAlive() {
  if (_keepAliveToken == nullptr) {
    // Open an active async handler to keep Node alive
    _keepAliveToken = Async::GetAsyncToken();
  }

  return _keepAliveToken != nullptr;
}

void UWPAddOn::ReleaseKeepAlive() {
  if (_keepAliveToken != nullptr) {
    auto token = _keepAliveToken;
    _keepAliveToken = nullptr;

    Async::ReleaseAsyncToken(token);
  }
}

void UWPAddOn::Init(Handle<Object> target) {
  Nan::HandleScope scope;

  NodeUtils::g_mainThreadId =
    std::this_thread::get_id();  // Capture entering thread id

  if (!s_instance.EnsureCoInitialized()) {
    return;
  }

  JsErrorCode err = JsSetProjectionEnqueueCallback(
    [](JsProjectionCallback jsCallback,
       JsProjectionCallbackContext jsContext, void *context) {
    Async::RunOnMain([jsCallback, jsContext]() {
      jsCallback(jsContext);
    });
  },
    /*projectionEnqueueContext*/nullptr);
  if (err != JsNoError) {
    Nan::ThrowError("JsSetProjectionEnqueueCallback failed");
    return;
  }

  Nan::SetMethod(target, "projectNamespace", ProjectNamespace);
  Nan::SetMethod(target, "close", Close);
}

NAN_METHOD(UWPAddOn::ProjectNamespace) {
  Nan::HandleScope scope;

  if (!info[0]->IsString()) {
    Nan::ThrowTypeError("Argument must be a string");
    return;
  }

  if (!s_instance.EnsureCoInitialized()) {
    return;
  }

  String::Value name(info[0]);
  if (JsProjectWinRTNamespace(reinterpret_cast<wchar_t*>(*name)) != JsNoError) {
    Nan::ThrowError("JsProjectWinRTNamespace failed");
	return;
  }

  // Keep Node alive once successfully projected a UWP namespace
  s_instance.EnsureKeepAlive();
  return;
}

NAN_METHOD(UWPAddOn::Close) {
  Nan::HandleScope scope;

  s_instance.ReleaseKeepAlive();
  s_instance.EnsureCoUninitialized();
  return;
}

NODE_MODULE(uwp, UWPAddOn::Init);
<|endoftext|>


<commit_before>#include "chainerx/cuda/memory_pool.h"

#include <mutex>
#include <unordered_map>
#include <vector>

#include "chainerx/cuda/cuda_runtime.h"
#include "chainerx/cuda/cuda_set_device_scope.h"
#include "chainerx/macro.h"

namespace chainerx {
namespace cuda {

MallocStatus DeviceMemoryAllocator::Malloc(void** ptr, size_t bytesize) {
    cudaError_t status = cudaMallocManaged(ptr, bytesize, cudaMemAttachGlobal);
    switch (status) {
        case cudaSuccess:
            return MallocStatus::kSuccess;
        case cudaErrorMemoryAllocation:
            return MallocStatus::kErrorMemoryAllocation;
        default:
            Throw(status);
    }
    CHAINERX_NEVER_REACH();
}

MallocStatus PinnedMemoryAllocator::Malloc(void** ptr, size_t bytesize) {
    cudaError_t status = cudaHostAlloc(ptr, bytesize, cudaHostAllocWriteCombined);
    switch (status) {
        case cudaSuccess:
            return MallocStatus::kSuccess;
        case cudaErrorMemoryAllocation:
            return MallocStatus::kErrorMemoryAllocation;
        default:
            Throw(status);
    }
    CHAINERX_NEVER_REACH();
}

MemoryPool::~MemoryPool() {
    // NOTE: CudaSetDeviceScope is not available at dtor because it may throw
    int orig_device_index{0};
    cudaGetDevice(&orig_device_index);
    cudaSetDevice(device_index_);

    for (const std::vector<void*>& free_list : free_bins_) {
        for (void* ptr : free_list) {
            allocator_->Free(ptr);
        }
    }
    // Ideally, in_use_ should be empty, but it could happen that shared ptrs to memories allocated
    // by this memory pool are released after this memory pool is destructed.
    // Our approach is that we anyway free CUDA memories held by this memory pool here in such case.
    // Operators of arrays holding such memories will be broken, but are not supported.
    for (const auto& item : in_use_) {
        void* ptr = item.first;
        allocator_->Free(ptr);
    }

    cudaSetDevice(orig_device_index);
}

void MemoryPool::FreeUnusedBlocks() {
    CudaSetDeviceScope scope{device_index_};
    std::lock_guard<std::mutex> lock{free_bins_mutex_};
    for (const std::vector<void*>& free_list : free_bins_) {
        for (void* ptr : free_list) {
            allocator_->Free(ptr);
        }
    }
    free_bins_.clear();
}

void* MemoryPool::Malloc(size_t bytesize) {
    if (bytesize == 0) {
        return nullptr;
    }

    size_t index = (bytesize - 1) / kAllocationUnitSize;

    void* ptr = nullptr;
    {
        std::lock_guard<std::mutex> lock{free_bins_mutex_};

        if (index < free_bins_.size()) {
            std::vector<void*>& free_list = free_bins_[index];
            if (!free_list.empty()) {
                ptr = free_list.back();
                CHAINERX_ASSERT(ptr != nullptr);
                free_list.pop_back();
            }
        }
    }

    // TODO(niboshi): Currently the deleter of allocated memory assumes
    // the memory is store in the memory pool (in `in_use_`), but this may not hold if some exception is thrown before it is stored.
    // `std::lock_guard` and `in_use_.emplace` are the sources of possible exceptions.
    if (ptr == nullptr) {
        size_t allocation_size = (index + 1) * kAllocationUnitSize;
        CudaSetDeviceScope scope{device_index_};
        MallocStatus status = allocator_->Malloc(&ptr, allocation_size);
        if (status == MallocStatus::kErrorMemoryAllocation) {
            FreeUnusedBlocks();
            status = allocator_->Malloc(&ptr, allocation_size);
            if (status == MallocStatus::kErrorMemoryAllocation) {
                // TODO(sonots): Include total pooled bytes in the error message
                throw OutOfMemoryError{bytesize};
            }
        }
    }

    {
        std::lock_guard<std::mutex> lock{in_use_mutex_};
        in_use_.emplace(ptr, index);
    }

    return ptr;
}

void MemoryPool::Free(void* ptr) {
    if (ptr == nullptr) {
        return;
    }
    size_t index{};

    {
        std::lock_guard<std::mutex> lock{in_use_mutex_};
        auto it = in_use_.find(ptr);
        if (it == in_use_.end()) {
            throw ChainerxError{"Cannot free out-of-pool memory"};
        }
        index = it->second;
        in_use_.erase(it);
    }

    {
        std::lock_guard<std::mutex> lock{free_bins_mutex_};
        if (free_bins_.size() <= index) {
            free_bins_.resize(index + 1);
        }
        std::vector<void*>& free_list = free_bins_[index];
        free_list.emplace_back(ptr);
    }
}

void MemoryPool::FreeNoExcept(void* ptr) noexcept {
    try {
        Free(ptr);
    } catch (...) {
        CHAINERX_NEVER_REACH();
    }
}

}  // namespace cuda
}  // namespace chainerx
<commit_msg>Update chainerx_cc/chainerx/cuda/memory_pool.cc<commit_after>#include "chainerx/cuda/memory_pool.h"

#include <mutex>
#include <unordered_map>
#include <vector>

#include "chainerx/cuda/cuda_runtime.h"
#include "chainerx/cuda/cuda_set_device_scope.h"
#include "chainerx/macro.h"

namespace chainerx {
namespace cuda {

MallocStatus DeviceMemoryAllocator::Malloc(void** ptr, size_t bytesize) {
    cudaError_t status = cudaMallocManaged(ptr, bytesize, cudaMemAttachGlobal);
    switch (status) {
        case cudaSuccess:
            return MallocStatus::kSuccess;
        case cudaErrorMemoryAllocation:
            return MallocStatus::kErrorMemoryAllocation;
        default:
            Throw(status);
    }
    CHAINERX_NEVER_REACH();
}

MallocStatus PinnedMemoryAllocator::Malloc(void** ptr, size_t bytesize) {
    cudaError_t status = cudaHostAlloc(ptr, bytesize, cudaHostAllocWriteCombined);
    switch (status) {
        case cudaSuccess:
            return MallocStatus::kSuccess;
        case cudaErrorMemoryAllocation:
            return MallocStatus::kErrorMemoryAllocation;
        default:
            Throw(status);
    }
    CHAINERX_NEVER_REACH();
}

MemoryPool::~MemoryPool() {
    // NOTE: CudaSetDeviceScope is not available at dtor because it may throw
    int orig_device_index{0};
    cudaGetDevice(&orig_device_index);
    cudaSetDevice(device_index_);

    for (const std::vector<void*>& free_list : free_bins_) {
        for (void* ptr : free_list) {
            allocator_->Free(ptr);
        }
    }
    // Ideally, in_use_ should be empty, but it could happen that shared ptrs to memories allocated
    // by this memory pool are released after this memory pool is destructed.
    // Our approach is that we anyway free CUDA memories held by this memory pool here in such case.
    // Operators of arrays holding such memories will be broken, but are not supported.
    for (const auto& item : in_use_) {
        void* ptr = item.first;
        allocator_->Free(ptr);
    }

    cudaSetDevice(orig_device_index);
}

void MemoryPool::FreeUnusedBlocks() {
    CudaSetDeviceScope scope{device_index_};
    std::lock_guard<std::mutex> lock{free_bins_mutex_};
    for (const std::vector<void*>& free_list : free_bins_) {
        for (void* ptr : free_list) {
            allocator_->Free(ptr);
        }
    }
    free_bins_.clear();
}

void* MemoryPool::Malloc(size_t bytesize) {
    if (bytesize == 0) {
        return nullptr;
    }

    size_t index = (bytesize - 1) / kAllocationUnitSize;

    void* ptr = nullptr;
    {
        std::lock_guard<std::mutex> lock{free_bins_mutex_};

        if (index < free_bins_.size()) {
            std::vector<void*>& free_list = free_bins_[index];
            if (!free_list.empty()) {
                ptr = free_list.back();
                CHAINERX_ASSERT(ptr != nullptr);
                free_list.pop_back();
            }
        }
    }

    // TODO(niboshi): Currently the deleter of allocated memory assumes that
    // the memory is store in the memory pool (in `in_use_`), but this may not hold if some exception is thrown before it is stored.
    // `std::lock_guard` and `in_use_.emplace` are the sources of possible exceptions.
    if (ptr == nullptr) {
        size_t allocation_size = (index + 1) * kAllocationUnitSize;
        CudaSetDeviceScope scope{device_index_};
        MallocStatus status = allocator_->Malloc(&ptr, allocation_size);
        if (status == MallocStatus::kErrorMemoryAllocation) {
            FreeUnusedBlocks();
            status = allocator_->Malloc(&ptr, allocation_size);
            if (status == MallocStatus::kErrorMemoryAllocation) {
                // TODO(sonots): Include total pooled bytes in the error message
                throw OutOfMemoryError{bytesize};
            }
        }
    }

    {
        std::lock_guard<std::mutex> lock{in_use_mutex_};
        in_use_.emplace(ptr, index);
    }

    return ptr;
}

void MemoryPool::Free(void* ptr) {
    if (ptr == nullptr) {
        return;
    }
    size_t index{};

    {
        std::lock_guard<std::mutex> lock{in_use_mutex_};
        auto it = in_use_.find(ptr);
        if (it == in_use_.end()) {
            throw ChainerxError{"Cannot free out-of-pool memory"};
        }
        index = it->second;
        in_use_.erase(it);
    }

    {
        std::lock_guard<std::mutex> lock{free_bins_mutex_};
        if (free_bins_.size() <= index) {
            free_bins_.resize(index + 1);
        }
        std::vector<void*>& free_list = free_bins_[index];
        free_list.emplace_back(ptr);
    }
}

void MemoryPool::FreeNoExcept(void* ptr) noexcept {
    try {
        Free(ptr);
    } catch (...) {
        CHAINERX_NEVER_REACH();
    }
}

}  // namespace cuda
}  // namespace chainerx
<|endoftext|>


<commit_before>#include "httpgetrequest.h"

#include "../../log/logger.h"

LOGGER(HTTPGetRequest);

HTTPGetRequest::HTTPGetRequest(QObject *parent)
: Measurement(parent)
, currentStatus(HTTPGetRequest::Unknown)
, nam(NULL)
, reply(NULL)
{
}

HTTPGetRequest::~HTTPGetRequest()
{
}

bool HTTPGetRequest::prepare(NetworkManager *networkManager, const MeasurementDefinitionPtr &measurementDefinition)
{
    Q_UNUSED(networkManager);
    definition = measurementDefinition.dynamicCast<HTTPGetRequestDefinition>();
    if ( definition.isNull() )
    {
        LOG_WARNING("Definition is empty");
        return false;
    }

    currentStatus = HTTPGetRequest::Unknown;

    // get network access manager
    nam = new QNetworkAccessManager(this);
    QObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));

    // prepare request
    request = QNetworkRequest(definition->url);

    return true;
}

bool HTTPGetRequest::start()
{
    // TODO start timer

    // start
    reply = nam->get(request);

    setStatus(HTTPGetRequest::Running);

    return true;
}

void HTTPGetRequest::setStatus(Status status)
{
    if (currentStatus != status)
    {
        currentStatus = status;
        emit statusChanged(status);
    }
}
<commit_msg>Implemented missing functions in HTTPGetRequest.<commit_after>#include "httpgetrequest.h"

#include "../../log/logger.h"

LOGGER(HTTPGetRequest);

HTTPGetRequest::HTTPGetRequest(QObject *parent)
: Measurement(parent)
, currentStatus(HTTPGetRequest::Unknown)
, nam(NULL)
, reply(NULL)
{
}

HTTPGetRequest::~HTTPGetRequest()
{
}

Measurement::Status HTTPGetRequest::status() const
{
    return currentStatus;
}

bool HTTPGetRequest::prepare(NetworkManager *networkManager, const MeasurementDefinitionPtr &measurementDefinition)
{
    Q_UNUSED(networkManager);
    definition = measurementDefinition.dynamicCast<HTTPGetRequestDefinition>();
    if ( definition.isNull() )
    {
        LOG_WARNING("Definition is empty");
        return false;
    }

    currentStatus = HTTPGetRequest::Unknown;

    // get network access manager
    nam = new QNetworkAccessManager(this);
    QObject::connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finished(QNetworkReply*)));

    // prepare request
    request = QNetworkRequest(definition->url);

    return true;
}

bool HTTPGetRequest::start()
{
    // TODO start timer

    // start
    reply = nam->get(request);

    setStatus(HTTPGetRequest::Running);

    return true;
}

bool HTTPGetRequest::stop()
{
    return true;
}

ResultPtr HTTPGetRequest::result() const
{
    return ResultPtr();
}

void HTTPGetRequest::setStatus(Status status)
{
    if (currentStatus != status)
    {
        currentStatus = status;
        emit statusChanged(status);
    }
}

void HTTPGetRequest::started()
{
}

void HTTPGetRequest::finished(QNetworkReply *reply)
{
}
<|endoftext|>


<commit_before>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2017 Axel Waggershauser
    Copyright (C) 2017-2018 Roman Lebedev

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

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

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

#include "decompressors/Cr2Decompressor.h"
#include "common/Common.h"                // for uint32, unroll_loop, ushort16
#include "common/Point.h"                 // for iPoint2D
#include "common/RawImage.h"              // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "io/BitPumpJPEG.h"               // for BitPumpJPEG
#include <algorithm>                      // for move, copy_n
#include <cassert>                        // for assert
#include <numeric>                        // for accumulate

using std::copy_n;

namespace rawspeed {

Cr2Decompressor::Cr2Decompressor(const ByteStream& bs, const RawImage& img)
    : AbstractLJpegDecompressor(bs, img) {
  if (mRaw->getDataType() != TYPE_USHORT16)
    ThrowRDE("Unexpected data type");

  if (!((mRaw->getCpp() == 1 && mRaw->getBpp() == 2) ||
        (mRaw->getCpp() == 3 && mRaw->getBpp() == 6)))
    ThrowRDE("Unexpected cpp: %u", mRaw->getCpp());

  if (!mRaw->dim.x || !mRaw->dim.y || mRaw->dim.x > 8896 ||
      mRaw->dim.y > 5920) {
    ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
             mRaw->dim.y);
  }
}

void Cr2Decompressor::decodeScan()
{
  if (predictorMode != 1)
    ThrowRDE("Unsupported predictor mode.");

  if (slicing.empty()) {
    const int slicesWidth = frame.w * frame.cps;
    if (slicesWidth > mRaw->dim.x)
      ThrowRDE("Don't know slicing pattern, and failed to guess it.");

    slicing = Cr2Slicing(/*numSlices=*/1, /*sliceWidth=don't care*/ 0,
                         /*lastSliceWidth=*/slicesWidth);
  }

  bool isSubSampled = false;
  for (uint32 i = 0; i < frame.cps;  i++)
    isSubSampled = isSubSampled || frame.compInfo[i].superH != 1 ||
                   frame.compInfo[i].superV != 1;

  if (isSubSampled) {
    if (mRaw->isCFA)
      ThrowRDE("Cannot decode subsampled image to CFA data");

    if (mRaw->getCpp() != frame.cps)
      ThrowRDE("Subsampled component count does not match image.");

    if (frame.cps != 3)
      ThrowRDE("Unsupported number of subsampled components: %u", frame.cps);

    // see http://lclevy.free.fr/cr2/#sraw for overview table
    bool isSupported = frame.compInfo[0].superH == 2;

    isSupported = isSupported && (frame.compInfo[0].superV == 1 ||
                                  frame.compInfo[0].superV == 2);

    for (uint32 i = 1; i < frame.cps; i++)
      isSupported = isSupported && frame.compInfo[i].superH == 1 &&
                    frame.compInfo[i].superV == 1;

    if (!isSupported) {
      ThrowRDE("Unsupported subsampling ([[%u, %u], [%u, %u], [%u, %u]])",
               frame.compInfo[0].superH, frame.compInfo[0].superV,
               frame.compInfo[1].superH, frame.compInfo[1].superV,
               frame.compInfo[2].superH, frame.compInfo[2].superV);
    }

    if (frame.compInfo[0].superV == 2)
      decodeN_X_Y<3, 2, 2>(); // Cr2 sRaw1/mRaw
    else {
      assert(frame.compInfo[0].superV == 1);
      decodeN_X_Y<3, 2, 1>(); // Cr2 sRaw2/sRaw
    }
  } else {
    switch (frame.cps) {
    case 2:
      decodeN_X_Y<2, 1, 1>();
      break;
    case 4:
      decodeN_X_Y<4, 1, 1>();
      break;
    default:
      ThrowRDE("Unsupported number of components: %u", frame.cps);
    }
  }
}

void Cr2Decompressor::decode(const Cr2Slicing& slicing_) {
  slicing = slicing_;
  for (auto sliceId = 0; sliceId < slicing.numSlices; sliceId++) {
    const auto sliceWidth = slicing.widthOfSlice(sliceId);
    if (sliceWidth <= 0)
      ThrowRDE("Bad slice width: %i", sliceWidth);
  }

  AbstractLJpegDecompressor::decode();
}

// N_COMP == number of components (2, 3 or 4)
// X_S_F  == x/horizontal sampling factor (1 or 2)
// Y_S_F  == y/vertical   sampling factor (1 or 2)

template <int N_COMP, int X_S_F, int Y_S_F>
void Cr2Decompressor::decodeN_X_Y()
{
  // To understand the CR2 slice handling and sampling factor behavior, see
  // https://github.com/lclevy/libcraw2/blob/master/docs/cr2_lossless.pdf?raw=true

  // inner loop decodes one group of pixels at a time
  //  * for <N,1,1>: N  = N*1*1 (full raw)
  //  * for <3,2,1>: 6  = 3*2*1
  //  * for <3,2,2>: 12 = 3*2*2
  // and advances x by N_COMP*X_S_F and y by Y_S_F
  constexpr int xStepSize = N_COMP * X_S_F;
  constexpr int yStepSize = Y_S_F;

  auto ht = getHuffmanTables<N_COMP>();
  auto pred = getInitialPredictors<N_COMP>();
  auto predNext = reinterpret_cast<ushort16*>(mRaw->getDataUncropped(0, 0));

  BitPumpJPEG bitStream(input);

  uint32 pixelPitch = mRaw->pitch / 2; // Pitch in pixel
  if (frame.cps != 3 && frame.w * frame.cps > 2 * frame.h) {
    // Fix Canon double height issue where Canon doubled the width and halfed
    // the height (e.g. with 5Ds), ask Canon. frame.w needs to stay as is here
    // because the number of pixels after which the predictor gets updated is
    // still the doubled width.
    // see: FIX_CANON_HALF_HEIGHT_DOUBLE_WIDTH
    frame.h *= 2;
  }

  if (X_S_F == 2 && Y_S_F == 1)
  {
    // fix the inconsistent slice width in sRaw mode, ask Canon.
    for (auto* width : {&slicing.sliceWidth, &slicing.lastSliceWidth})
      *width = (*width) * 3 / 2;
  }

  for (const auto& width : {slicing.sliceWidth, slicing.lastSliceWidth}) {
    if (width > mRaw->dim.x)
      ThrowRDE("Slice is longer than image's height, which is unsupported.");
    if (width % xStepSize != 0) {
      ThrowRDE("Slice width (%u) should be multiple of pixel group size (%u)",
               width, xStepSize);
    }
  }

  if (frame.h * slicing.totalWidth() < mRaw->getCpp() * mRaw->dim.area())
    ThrowRDE("Incorrrect slice height / slice widths! Less than image size.");

  unsigned processedPixels = 0;
  unsigned processedLineSlices = 0;
  for (auto sliceId = 0; sliceId < slicing.numSlices; sliceId++) {
    const unsigned sliceWidth = slicing.widthOfSlice(sliceId);

    assert(frame.h % yStepSize == 0);
    for (unsigned y = 0; y < frame.h; y += yStepSize) {
      // Fix for Canon 80D mraw format.
      // In that format, `frame` is 4032x3402, while `mRaw` is 4536x3024.
      // Consequently, the slices in `frame` wrap around plus there are few
      // 'extra' sliced lines because sum(slicesW) * sliceH > mRaw->dim.area()
      // Those would overflow, hence the break.
      // see FIX_CANON_FRAME_VS_IMAGE_SIZE_MISMATCH
      unsigned destY = processedLineSlices % mRaw->dim.y;
      unsigned destX = processedLineSlices / mRaw->dim.y * slicing.sliceWidth /
                       mRaw->getCpp();
      if (destX >= static_cast<unsigned>(mRaw->dim.x))
        break;
      auto dest =
          reinterpret_cast<ushort16*>(mRaw->getDataUncropped(destX, destY));

      assert(sliceWidth % xStepSize == 0);
      if (X_S_F == 1) {
        if (destX + sliceWidth > static_cast<unsigned>(mRaw->dim.x))
          ThrowRDE("Bad slice width / frame size / image size combination.");
      } else {
        // FIXME.
      }
      for (unsigned x = 0; x < sliceWidth; x += xStepSize) {
        // check if we processed one full raw row worth of pixels
        if (processedPixels == frame.w) {
          // if yes -> update predictor by going back exactly one row,
          // no matter where we are right now.
          // makes no sense from an image compression point of view, ask Canon.
          copy_n(predNext, N_COMP, pred.data());
          predNext = dest;
          processedPixels = 0;
        }

        if (X_S_F == 1) { // will be optimized out
          unroll_loop<N_COMP>([&](int i) {
            dest[i] = pred[i] += ht[i]->decodeNext(bitStream);
          });
        } else {
          unroll_loop<Y_S_F>([&](int i) {
            dest[0 + i*pixelPitch] = pred[0] += ht[0]->decodeNext(bitStream);
            dest[3 + i*pixelPitch] = pred[0] += ht[0]->decodeNext(bitStream);
          });

          dest[1] = pred[1] += ht[1]->decodeNext(bitStream);
          dest[2] = pred[2] += ht[2]->decodeNext(bitStream);
        }

        dest += xStepSize;
        processedPixels += X_S_F;
      }

      processedLineSlices += yStepSize;
    }
  }
}

} // namespace rawspeed
<commit_msg>Cr2Decompressor::decodeN_X_Y(): use larger integer size in sanity check<commit_after>/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009-2014 Klaus Post
    Copyright (C) 2017 Axel Waggershauser
    Copyright (C) 2017-2018 Roman Lebedev

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

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

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

#include "decompressors/Cr2Decompressor.h"
#include "common/Common.h"                // for uint32, unroll_loop, ushort16
#include "common/Point.h"                 // for iPoint2D
#include "common/RawImage.h"              // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "io/BitPumpJPEG.h"               // for BitPumpJPEG
#include <algorithm>                      // for move, copy_n
#include <cassert>                        // for assert
#include <numeric>                        // for accumulate

using std::copy_n;

namespace rawspeed {

Cr2Decompressor::Cr2Decompressor(const ByteStream& bs, const RawImage& img)
    : AbstractLJpegDecompressor(bs, img) {
  if (mRaw->getDataType() != TYPE_USHORT16)
    ThrowRDE("Unexpected data type");

  if (!((mRaw->getCpp() == 1 && mRaw->getBpp() == 2) ||
        (mRaw->getCpp() == 3 && mRaw->getBpp() == 6)))
    ThrowRDE("Unexpected cpp: %u", mRaw->getCpp());

  if (!mRaw->dim.x || !mRaw->dim.y || mRaw->dim.x > 8896 ||
      mRaw->dim.y > 5920) {
    ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
             mRaw->dim.y);
  }
}

void Cr2Decompressor::decodeScan()
{
  if (predictorMode != 1)
    ThrowRDE("Unsupported predictor mode.");

  if (slicing.empty()) {
    const int slicesWidth = frame.w * frame.cps;
    if (slicesWidth > mRaw->dim.x)
      ThrowRDE("Don't know slicing pattern, and failed to guess it.");

    slicing = Cr2Slicing(/*numSlices=*/1, /*sliceWidth=don't care*/ 0,
                         /*lastSliceWidth=*/slicesWidth);
  }

  bool isSubSampled = false;
  for (uint32 i = 0; i < frame.cps;  i++)
    isSubSampled = isSubSampled || frame.compInfo[i].superH != 1 ||
                   frame.compInfo[i].superV != 1;

  if (isSubSampled) {
    if (mRaw->isCFA)
      ThrowRDE("Cannot decode subsampled image to CFA data");

    if (mRaw->getCpp() != frame.cps)
      ThrowRDE("Subsampled component count does not match image.");

    if (frame.cps != 3)
      ThrowRDE("Unsupported number of subsampled components: %u", frame.cps);

    // see http://lclevy.free.fr/cr2/#sraw for overview table
    bool isSupported = frame.compInfo[0].superH == 2;

    isSupported = isSupported && (frame.compInfo[0].superV == 1 ||
                                  frame.compInfo[0].superV == 2);

    for (uint32 i = 1; i < frame.cps; i++)
      isSupported = isSupported && frame.compInfo[i].superH == 1 &&
                    frame.compInfo[i].superV == 1;

    if (!isSupported) {
      ThrowRDE("Unsupported subsampling ([[%u, %u], [%u, %u], [%u, %u]])",
               frame.compInfo[0].superH, frame.compInfo[0].superV,
               frame.compInfo[1].superH, frame.compInfo[1].superV,
               frame.compInfo[2].superH, frame.compInfo[2].superV);
    }

    if (frame.compInfo[0].superV == 2)
      decodeN_X_Y<3, 2, 2>(); // Cr2 sRaw1/mRaw
    else {
      assert(frame.compInfo[0].superV == 1);
      decodeN_X_Y<3, 2, 1>(); // Cr2 sRaw2/sRaw
    }
  } else {
    switch (frame.cps) {
    case 2:
      decodeN_X_Y<2, 1, 1>();
      break;
    case 4:
      decodeN_X_Y<4, 1, 1>();
      break;
    default:
      ThrowRDE("Unsupported number of components: %u", frame.cps);
    }
  }
}

void Cr2Decompressor::decode(const Cr2Slicing& slicing_) {
  slicing = slicing_;
  for (auto sliceId = 0; sliceId < slicing.numSlices; sliceId++) {
    const auto sliceWidth = slicing.widthOfSlice(sliceId);
    if (sliceWidth <= 0)
      ThrowRDE("Bad slice width: %i", sliceWidth);
  }

  AbstractLJpegDecompressor::decode();
}

// N_COMP == number of components (2, 3 or 4)
// X_S_F  == x/horizontal sampling factor (1 or 2)
// Y_S_F  == y/vertical   sampling factor (1 or 2)

template <int N_COMP, int X_S_F, int Y_S_F>
void Cr2Decompressor::decodeN_X_Y()
{
  // To understand the CR2 slice handling and sampling factor behavior, see
  // https://github.com/lclevy/libcraw2/blob/master/docs/cr2_lossless.pdf?raw=true

  // inner loop decodes one group of pixels at a time
  //  * for <N,1,1>: N  = N*1*1 (full raw)
  //  * for <3,2,1>: 6  = 3*2*1
  //  * for <3,2,2>: 12 = 3*2*2
  // and advances x by N_COMP*X_S_F and y by Y_S_F
  constexpr int xStepSize = N_COMP * X_S_F;
  constexpr int yStepSize = Y_S_F;

  auto ht = getHuffmanTables<N_COMP>();
  auto pred = getInitialPredictors<N_COMP>();
  auto predNext = reinterpret_cast<ushort16*>(mRaw->getDataUncropped(0, 0));

  BitPumpJPEG bitStream(input);

  uint32 pixelPitch = mRaw->pitch / 2; // Pitch in pixel
  if (frame.cps != 3 && frame.w * frame.cps > 2 * frame.h) {
    // Fix Canon double height issue where Canon doubled the width and halfed
    // the height (e.g. with 5Ds), ask Canon. frame.w needs to stay as is here
    // because the number of pixels after which the predictor gets updated is
    // still the doubled width.
    // see: FIX_CANON_HALF_HEIGHT_DOUBLE_WIDTH
    frame.h *= 2;
  }

  if (X_S_F == 2 && Y_S_F == 1)
  {
    // fix the inconsistent slice width in sRaw mode, ask Canon.
    for (auto* width : {&slicing.sliceWidth, &slicing.lastSliceWidth})
      *width = (*width) * 3 / 2;
  }

  for (const auto& width : {slicing.sliceWidth, slicing.lastSliceWidth}) {
    if (width > mRaw->dim.x)
      ThrowRDE("Slice is longer than image's height, which is unsupported.");
    if (width % xStepSize != 0) {
      ThrowRDE("Slice width (%u) should be multiple of pixel group size (%u)",
               width, xStepSize);
    }
  }

  if (iPoint2D::area_type(frame.h) * slicing.totalWidth() <
      mRaw->getCpp() * mRaw->dim.area())
    ThrowRDE("Incorrrect slice height / slice widths! Less than image size.");

  unsigned processedPixels = 0;
  unsigned processedLineSlices = 0;
  for (auto sliceId = 0; sliceId < slicing.numSlices; sliceId++) {
    const unsigned sliceWidth = slicing.widthOfSlice(sliceId);

    assert(frame.h % yStepSize == 0);
    for (unsigned y = 0; y < frame.h; y += yStepSize) {
      // Fix for Canon 80D mraw format.
      // In that format, `frame` is 4032x3402, while `mRaw` is 4536x3024.
      // Consequently, the slices in `frame` wrap around plus there are few
      // 'extra' sliced lines because sum(slicesW) * sliceH > mRaw->dim.area()
      // Those would overflow, hence the break.
      // see FIX_CANON_FRAME_VS_IMAGE_SIZE_MISMATCH
      unsigned destY = processedLineSlices % mRaw->dim.y;
      unsigned destX = processedLineSlices / mRaw->dim.y * slicing.sliceWidth /
                       mRaw->getCpp();
      if (destX >= static_cast<unsigned>(mRaw->dim.x))
        break;
      auto dest =
          reinterpret_cast<ushort16*>(mRaw->getDataUncropped(destX, destY));

      assert(sliceWidth % xStepSize == 0);
      if (X_S_F == 1) {
        if (destX + sliceWidth > static_cast<unsigned>(mRaw->dim.x))
          ThrowRDE("Bad slice width / frame size / image size combination.");
      } else {
        // FIXME.
      }
      for (unsigned x = 0; x < sliceWidth; x += xStepSize) {
        // check if we processed one full raw row worth of pixels
        if (processedPixels == frame.w) {
          // if yes -> update predictor by going back exactly one row,
          // no matter where we are right now.
          // makes no sense from an image compression point of view, ask Canon.
          copy_n(predNext, N_COMP, pred.data());
          predNext = dest;
          processedPixels = 0;
        }

        if (X_S_F == 1) { // will be optimized out
          unroll_loop<N_COMP>([&](int i) {
            dest[i] = pred[i] += ht[i]->decodeNext(bitStream);
          });
        } else {
          unroll_loop<Y_S_F>([&](int i) {
            dest[0 + i*pixelPitch] = pred[0] += ht[0]->decodeNext(bitStream);
            dest[3 + i*pixelPitch] = pred[0] += ht[0]->decodeNext(bitStream);
          });

          dest[1] = pred[1] += ht[1]->decodeNext(bitStream);
          dest[2] = pred[2] += ht[2]->decodeNext(bitStream);
        }

        dest += xStepSize;
        processedPixels += X_S_F;
      }

      processedLineSlices += yStepSize;
    }
  }
}

} // namespace rawspeed
<|endoftext|>