<commit_before>#include "thumbnail_manager.hpp"

#include <algorithm> // find

#include "algorithm.hpp"

thumbnail_manager::thumbnail_manager(x_connection & c,
                                     const layout_t * layout,
                                     const thumbnail_t::factory * factory)
  : _c(c), _layout(layout), _factory(factory)
{
  _c.attach(0, XCB_PROPERTY_NOTIFY, this);
  _c.attach(20, XCB_CONFIGURE_NOTIFY, this);
  _c.update_input(_c.root_window(), XCB_EVENT_MASK_PROPERTY_CHANGE);
}

thumbnail_manager::~thumbnail_manager(void)
{
  _c.detach(XCB_PROPERTY_NOTIFY, this);
  _c.detach(XCB_CONFIGURE_NOTIFY, this);
}

void
thumbnail_manager::show(void)
{
  _active = true;

  update();

  _cyclic_iterator = window_cyclic_iterator(&_windows);
  _next_window = *(_cyclic_iterator + 1);
  _current_window = *_cyclic_iterator;

  for (auto & item : _thumbnails) {
    item.second->show().update();
  }
}

void
thumbnail_manager::hide(void)
{
  _active = false;

  for (auto & item : _thumbnails) {
    item.second->hide();
  }
}

void
thumbnail_manager::next(void) { next_or_prev(true); }

void
thumbnail_manager::prev(void) { next_or_prev(false); }

void
thumbnail_manager::select(const xcb_window_t & window)
{
  if (window == XCB_NONE) {
    try {
      _thumbnails.at(*_cyclic_iterator)->select();
    } catch (...) {}

  } else {
    for (auto & item : _thumbnails) {
      if (item.second->id() == window) {
        item.second->select();
        break;
      }
    }
  }
}

void
thumbnail_manager::highlight(const unsigned int & window)
{
  for (auto & item : _thumbnails) {
    if (item.second->id() == window) {
      try {
        _thumbnails.at(_current_window)->highlight(false).update();
        item.second->highlight(true).update();
        while (*_cyclic_iterator != item.first) ++_cyclic_iterator;
        _next_window = *(_cyclic_iterator + 1);
        _current_window = *_cyclic_iterator;
      } catch (...) {}

      break;
    }
  }
}

void
thumbnail_manager::east(void)
{
  xcb_window_t tid = nearest_thumbnail(
      std::bind(&thumbnail_manager::is_east, this, std::placeholders::_1));
  if (tid != XCB_NONE) highlight(tid);
}

void
thumbnail_manager::west(void)
{
  xcb_window_t tid = nearest_thumbnail(
      std::bind(&thumbnail_manager::is_west, this, std::placeholders::_1));
  if (tid != XCB_NONE) highlight(tid);
}

void
thumbnail_manager::north(void)
{
  xcb_window_t tid = nearest_thumbnail(
      std::bind(&thumbnail_manager::is_north, this, std::placeholders::_1));
  if (tid != XCB_NONE) highlight(tid);
}

void
thumbnail_manager::south(void)
{
  xcb_window_t tid = nearest_thumbnail(
      std::bind(&thumbnail_manager::is_south, this, std::placeholders::_1));
  if (tid != XCB_NONE) highlight(tid);
}

bool
thumbnail_manager::handle(xcb_generic_event_t * ge)
{
  if (XCB_PROPERTY_NOTIFY == (ge->response_type & ~0x80)) {
    xcb_property_notify_event_t * e = (xcb_property_notify_event_t *)ge;
    if (_active
        && e->window == _c.root_window()
        && e->atom == _c.intern_atom("_NET_CLIENT_LIST_STACKING"))
    {
      update();
      reset();
    }
    return true;

  } else if (XCB_CONFIGURE_NOTIFY == (ge->response_type & ~0x80)) {
    if (_active) {
      auto rects = _layout->arrange(query_current_screen(), _windows.size());
      for (size_t i = 0; i < _windows.size(); ++i) {
        try {
          _thumbnails.at(_windows[i])->update(rects[i]).update();
        } catch (...) {}
      }
    }

    return true;
  }

  return false;
}

inline void
thumbnail_manager::reset(void)
{
  for (auto & item : _thumbnails) {
    item.second->highlight(false).show().update();
  }

  bool found = false;
  _cyclic_iterator = window_cyclic_iterator(&_windows);

  // search for current thumbnail
  for (std::size_t i = 0; i < _windows.size(); ++i) {
    if (*_cyclic_iterator == _current_window) {
      found = true;
      break;
    } else {
      ++_cyclic_iterator;
    }
  }

  // search for next thumbnail if current was not found
  if (! found) {
    _cyclic_iterator = window_cyclic_iterator(&_windows);

    for (std::size_t i = 0; i < _windows.size(); ++i) {
      if (*_cyclic_iterator == _next_window) {
        break;
      } else {
        ++_cyclic_iterator;
      }
    }
  }

  _next_window = *(_cyclic_iterator + 1);
  _current_window = *_cyclic_iterator;

  try {
    _thumbnails.at(*_cyclic_iterator)->highlight(true).update();
  } catch (...) {}
}

inline void
thumbnail_manager::update(void)
{
  _windows = _c.net_client_list_stacking();
  auto rects = _layout->arrange(query_current_screen(), _windows.size());

  for (auto item = _thumbnails.begin(); item != _thumbnails.end(); ) {
    auto result = std::find(_windows.begin(), _windows.end(), item->first);
    if (result == _windows.end()) {
      item = _thumbnails.erase(item);
    } else {
      ++item;
    }
  }

  for (size_t i = 0; i < _windows.size(); ++i) {
    auto result = _thumbnails.find(_windows[i]);

    if (result == _thumbnails.end()) {
      _thumbnails[_windows[i]] = _factory->make(_windows[i], rects[i]);
    } else {
      result->second->update(rects[i]);
    }
  }
}

void
thumbnail_manager::next_or_prev(bool next)
{
  try {
    _thumbnails.at(*_cyclic_iterator)->highlight(false).update();
    next ? ++_cyclic_iterator : --_cyclic_iterator;
    _thumbnails.at(*_cyclic_iterator)->highlight(true).update();
  } catch (...) {}

  _next_window = *(_cyclic_iterator + 1);
  _current_window = *_cyclic_iterator;
}

inline xcb_window_t
thumbnail_manager::
nearest_thumbnail(const std::function<bool(double)> & direction)
{
  xcb_window_t thumbnail_id = XCB_NONE;

  try {
    auto & current = _thumbnails.at(_current_window);
    auto & r1 = current->rect();

    // in X (x,y) coordinates are actually flipped on the x axis
    // this means that (0,0) is in the top left corner, not in bottom left
    auto p1 = std::make_tuple(  r1.x() + (r1.width()  / 2),
                              -(r1.y() + (r1.height() / 2)));

    double min_distance = 0xffffffff;

    for (auto & item : _thumbnails) {
      if (item.second->id() == current->id()) {
        continue;
      } else {
        auto & r2 = item.second->rect();
        // in X (x,y) coordinates are actually flipped on the x axis
        // this means that (0,0) is in the top left corner, not in bottom left
        auto p2 = std::make_tuple(  r2.x() + (r2.width()  / 2),
                                  -(r2.y() + (r2.height() / 2)));

        if (direction(algorithm::angle()(p1, p2))) {
          double distance = algorithm::distance()(p1, p2);
          if (distance < min_distance) {
            min_distance = distance;
            thumbnail_id = item.second->id();
          }
        }
      }
    }

  } catch (...) {}

  return thumbnail_id;
}

// 2*M_PI ^= 360°
// 2*M_PI - M_PI/4 ^= 315°
// 2*M_PI - M_PI/2 ^= 270°
// M_PI + M_PI/4 ^= 225°
// M_PI ^= 180°
// M_PI - M_PI/4 ^= 135°
// M_PI/2 ^= 90°
// M_PI/4 ^= 45°

inline bool
thumbnail_manager::is_east(double angle)
{
  // (>=0° && <=45°) || >= 315°
  return (angle >= 0 && angle <= M_PI/4) || angle >= 7*M_PI/4;
}

inline bool
thumbnail_manager::is_west(double angle)
{
  // >=135° && <=225°
  return angle >= 3*M_PI/4 && angle <= 5*M_PI/4;
}

inline bool
thumbnail_manager::is_north(double angle)
{
  // >=45° && <=135°
  return angle >= M_PI/4 && angle <= 3*M_PI/4;
}

inline bool
thumbnail_manager::is_south(double angle)
{
  // >=225° && <= 315°
  return angle >= 5*M_PI/4 && angle <= 7*M_PI/4;
}

rectangle
thumbnail_manager::query_current_screen(void)
{
  rectangle screen = { 0, 0, 800, 600 };

  try {
    auto pos = _c.query_pointer();
    screen = _c.current_screen(pos.first);
  } catch (...) {}

  return screen;
}
<commit_msg>Remove non-iterator specific code from reset() method<commit_after>#include "thumbnail_manager.hpp"

#include <algorithm> // find

#include "algorithm.hpp"

thumbnail_manager::thumbnail_manager(x_connection & c,
                                     const layout_t * layout,
                                     const thumbnail_t::factory * factory)
  : _c(c), _layout(layout), _factory(factory)
{
  _c.attach(0, XCB_PROPERTY_NOTIFY, this);
  _c.attach(20, XCB_CONFIGURE_NOTIFY, this);
  _c.update_input(_c.root_window(), XCB_EVENT_MASK_PROPERTY_CHANGE);
}

thumbnail_manager::~thumbnail_manager(void)
{
  _c.detach(XCB_PROPERTY_NOTIFY, this);
  _c.detach(XCB_CONFIGURE_NOTIFY, this);
}

void
thumbnail_manager::show(void)
{
  _active = true;

  update();

  _cyclic_iterator = window_cyclic_iterator(&_windows);
  _next_window = *(_cyclic_iterator + 1);
  _current_window = *_cyclic_iterator;

  for (auto & item : _thumbnails) {
    item.second->show().update();
  }
}

void
thumbnail_manager::hide(void)
{
  _active = false;

  for (auto & item : _thumbnails) {
    item.second->hide();
  }
}

void
thumbnail_manager::next(void) { next_or_prev(true); }

void
thumbnail_manager::prev(void) { next_or_prev(false); }

void
thumbnail_manager::select(const xcb_window_t & window)
{
  if (window == XCB_NONE) {
    try {
      _thumbnails.at(*_cyclic_iterator)->select();
    } catch (...) {}

  } else {
    for (auto & item : _thumbnails) {
      if (item.second->id() == window) {
        item.second->select();
        break;
      }
    }
  }
}

void
thumbnail_manager::highlight(const unsigned int & window)
{
  for (auto & item : _thumbnails) {
    if (item.second->id() == window) {
      try {
        _thumbnails.at(_current_window)->highlight(false).update();
        item.second->highlight(true).update();
        while (*_cyclic_iterator != item.first) ++_cyclic_iterator;
        _next_window = *(_cyclic_iterator + 1);
        _current_window = *_cyclic_iterator;
      } catch (...) {}

      break;
    }
  }
}

void
thumbnail_manager::east(void)
{
  xcb_window_t tid = nearest_thumbnail(
      std::bind(&thumbnail_manager::is_east, this, std::placeholders::_1));
  if (tid != XCB_NONE) highlight(tid);
}

void
thumbnail_manager::west(void)
{
  xcb_window_t tid = nearest_thumbnail(
      std::bind(&thumbnail_manager::is_west, this, std::placeholders::_1));
  if (tid != XCB_NONE) highlight(tid);
}

void
thumbnail_manager::north(void)
{
  xcb_window_t tid = nearest_thumbnail(
      std::bind(&thumbnail_manager::is_north, this, std::placeholders::_1));
  if (tid != XCB_NONE) highlight(tid);
}

void
thumbnail_manager::south(void)
{
  xcb_window_t tid = nearest_thumbnail(
      std::bind(&thumbnail_manager::is_south, this, std::placeholders::_1));
  if (tid != XCB_NONE) highlight(tid);
}

bool
thumbnail_manager::handle(xcb_generic_event_t * ge)
{
  if (XCB_PROPERTY_NOTIFY == (ge->response_type & ~0x80)) {
    xcb_property_notify_event_t * e = (xcb_property_notify_event_t *)ge;
    if (_active
        && e->window == _c.root_window()
        && e->atom == _c.intern_atom("_NET_CLIENT_LIST_STACKING"))
    {
      update();
      reset();

      try {
        _thumbnails.at(*_cyclic_iterator)->highlight(true).update();
      } catch (...) {}
    }

    return true;

  } else if (XCB_CONFIGURE_NOTIFY == (ge->response_type & ~0x80)) {
    if (_active) {
      auto rects = _layout->arrange(query_current_screen(), _windows.size());
      for (size_t i = 0; i < _windows.size(); ++i) {
        try {
          _thumbnails.at(_windows[i])->update(rects[i]).update();
        } catch (...) {}
      }
    }

    return true;
  }

  return false;
}

inline void
thumbnail_manager::reset(void)
{
  for (auto & item : _thumbnails) {
    item.second->highlight(false).show().update();
  }

  bool found = false;
  _cyclic_iterator = window_cyclic_iterator(&_windows);

  // search for current thumbnail
  for (std::size_t i = 0; i < _windows.size(); ++i) {
    if (*_cyclic_iterator == _current_window) {
      found = true;
      break;
    } else {
      ++_cyclic_iterator;
    }
  }

  // search for next thumbnail if current was not found
  if (! found) {
    _cyclic_iterator = window_cyclic_iterator(&_windows);

    for (std::size_t i = 0; i < _windows.size(); ++i) {
      if (*_cyclic_iterator == _next_window) {
        break;
      } else {
        ++_cyclic_iterator;
      }
    }
  }

  _next_window = *(_cyclic_iterator + 1);
  _current_window = *_cyclic_iterator;
}

inline void
thumbnail_manager::update(void)
{
  _windows = _c.net_client_list_stacking();
  auto rects = _layout->arrange(query_current_screen(), _windows.size());

  for (auto item = _thumbnails.begin(); item != _thumbnails.end(); ) {
    auto result = std::find(_windows.begin(), _windows.end(), item->first);
    if (result == _windows.end()) {
      item = _thumbnails.erase(item);
    } else {
      ++item;
    }
  }

  for (size_t i = 0; i < _windows.size(); ++i) {
    auto result = _thumbnails.find(_windows[i]);

    if (result == _thumbnails.end()) {
      _thumbnails[_windows[i]] = _factory->make(_windows[i], rects[i]);
    } else {
      result->second->update(rects[i]);
    }
  }
}

void
thumbnail_manager::next_or_prev(bool next)
{
  try {
    _thumbnails.at(*_cyclic_iterator)->highlight(false).update();
    next ? ++_cyclic_iterator : --_cyclic_iterator;
    _thumbnails.at(*_cyclic_iterator)->highlight(true).update();
  } catch (...) {}

  _next_window = *(_cyclic_iterator + 1);
  _current_window = *_cyclic_iterator;
}

inline xcb_window_t
thumbnail_manager::
nearest_thumbnail(const std::function<bool(double)> & direction)
{
  xcb_window_t thumbnail_id = XCB_NONE;

  try {
    auto & current = _thumbnails.at(_current_window);
    auto & r1 = current->rect();

    // in X (x,y) coordinates are actually flipped on the x axis
    // this means that (0,0) is in the top left corner, not in bottom left
    auto p1 = std::make_tuple(  r1.x() + (r1.width()  / 2),
                              -(r1.y() + (r1.height() / 2)));

    double min_distance = 0xffffffff;

    for (auto & item : _thumbnails) {
      if (item.second->id() == current->id()) {
        continue;
      } else {
        auto & r2 = item.second->rect();
        // in X (x,y) coordinates are actually flipped on the x axis
        // this means that (0,0) is in the top left corner, not in bottom left
        auto p2 = std::make_tuple(  r2.x() + (r2.width()  / 2),
                                  -(r2.y() + (r2.height() / 2)));

        if (direction(algorithm::angle()(p1, p2))) {
          double distance = algorithm::distance()(p1, p2);
          if (distance < min_distance) {
            min_distance = distance;
            thumbnail_id = item.second->id();
          }
        }
      }
    }

  } catch (...) {}

  return thumbnail_id;
}

// 2*M_PI ^= 360°
// 2*M_PI - M_PI/4 ^= 315°
// 2*M_PI - M_PI/2 ^= 270°
// M_PI + M_PI/4 ^= 225°
// M_PI ^= 180°
// M_PI - M_PI/4 ^= 135°
// M_PI/2 ^= 90°
// M_PI/4 ^= 45°

inline bool
thumbnail_manager::is_east(double angle)
{
  // (>=0° && <=45°) || >= 315°
  return (angle >= 0 && angle <= M_PI/4) || angle >= 7*M_PI/4;
}

inline bool
thumbnail_manager::is_west(double angle)
{
  // >=135° && <=225°
  return angle >= 3*M_PI/4 && angle <= 5*M_PI/4;
}

inline bool
thumbnail_manager::is_north(double angle)
{
  // >=45° && <=135°
  return angle >= M_PI/4 && angle <= 3*M_PI/4;
}

inline bool
thumbnail_manager::is_south(double angle)
{
  // >=225° && <= 315°
  return angle >= 5*M_PI/4 && angle <= 7*M_PI/4;
}

rectangle
thumbnail_manager::query_current_screen(void)
{
  rectangle screen = { 0, 0, 800, 600 };

  try {
    auto pos = _c.query_pointer();
    screen = _c.current_screen(pos.first);
  } catch (...) {}

  return screen;
}
<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * helloBPSZWrapper.cpp: Simple self-descriptive example of how to write a
 * variable to a BP File that lives in several MPI processes and is compressed
 * with SZ http://www.bzip.org/
 *
 *  Created on: Jul 26, 2017
 *      Author: William F Godoy godoywf@ornl.gov
 */
#include <mpi.h>

#include <ios>       //std::ios_base::failure
#include <iostream>  //std::cout
#include <numeric>   //std::iota
#include <stdexcept> //std::invalid_argument std::exception
#include <vector>

#include <adios2.h>

int main(int argc, char *argv[])
{
    MPI_Init(&argc, &argv);
    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    /** Application variable uints from 0 to 1000 */
    std::vector<double> myvars(1000);
    std::iota(myvars.begin(), myvars.end(), 0.f);
    const std::size_t Nx = myvars.size();
    const std::size_t inputBytes = Nx * sizeof(double);

    try
    {
        /** ADIOS class factory of IO class objects, DebugON is recommended */
        adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON);

        // Get a Transform of type SZ
        adios2::Operator &adiosSZ =
        adios.DefineOperator("SZVariableCompressor", "SZ");

        /*** IO class object: settings and factory of Settings: Variables,
         * Parameters, Transports, and Execution: Engines */
        adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N_SZ");

        /** global array : name, { shape (total) }, { start (local) }, { count
         * (local) }, all are constant dimensions */
        adios2::Variable<double> &var =
        bpIO.DefineVariable<double>("var", {size * Nx},
                                    {rank * Nx}, {Nx},
                                    adios2::ConstantDims);

        // 1st way: adding transform metadata to variable to Engine can decide:
        // &adiosSZ gets mapped to bpUInts.TransformInfo[SZID].Operator
        const unsigned int SZID = var.AddTransform(adiosSZ, {{"foo", "0.01"}});

        // 2nd way: treat Transforms as wrappers to underlying library.
        // you can redefine parameters
        const std::size_t estimatedSize = adiosSZ.BufferMaxSize(Nx * var.m_ElementSize);
        std::vector<char> compressedBuffer(estimatedSize);
        size_t compressedSize = adiosSZ.Compress(myvars.data(), var.m_Count, var.m_ElementSize,
                                                 var.m_Type, compressedBuffer.data(), {{"accuracy", "0.01"}});

        compressedBuffer.resize(compressedSize);

        std::cout << "Rank " << rank << "\n";
        std::cout << "Compression summary:\n";
        std::cout << "Input data size: " << inputBytes << " bytes\n";
        std::cout << "SZ estimated output size: " << estimatedSize
        << " bytes\n";
        std::cout << "SZ final output size: " << compressedSize
        << " bytes\n\n";

        // Allocate original data size
        std::vector<double> decompressedBuffer(Nx);
        size_t decompressedSize = adiosSZ.Decompress(compressedBuffer.data(), compressedSize,
                                                     decompressedBuffer.data(), var.m_Count, var.m_Type,
                                                     var.m_OperatorsInfo[SZID].Parameters);

        std::cout << "Decompression summary:\n";
        std::cout << "Decompressed size: " << decompressedSize << " bytes\n";
        std::cout << "Data:\n";

        for (int i=0; i<decompressedBuffer.size(); i++)
        {
            if (i % 25 == 0)
            {
                std::cout << "\n";
            }
            std::cout << decompressedBuffer[i] << " ";
        }
        std::cout << "\n";
    }
    catch (std::invalid_argument &e)
    {
        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
        << rank << "\n";
        std::cout << e.what() << "\n";
    }
    catch (std::ios_base::failure &e)
    {
        std::cout
        << "IO System base failure exception, STOPPING PROGRAM from rank "
        << rank << "\n";
        std::cout << e.what() << "\n";
    }
    catch (std::exception &e)
    {
        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
        std::cout << e.what() << "\n";
    }

    MPI_Finalize();

    return 0;
}
<commit_msg>Apply clang-format<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * helloBPSZWrapper.cpp: Simple self-descriptive example of how to write a
 * variable to a BP File that lives in several MPI processes and is compressed
 * with SZ http://www.bzip.org/
 *
 *  Created on: Jul 26, 2017
 *      Author: William F Godoy godoywf@ornl.gov
 */
#include <mpi.h>

#include <ios>       //std::ios_base::failure
#include <iostream>  //std::cout
#include <numeric>   //std::iota
#include <stdexcept> //std::invalid_argument std::exception
#include <vector>

#include <adios2.h>

int main(int argc, char *argv[])
{
    MPI_Init(&argc, &argv);
    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    /** Application variable uints from 0 to 1000 */
    std::vector<double> myvars(1000);
    std::iota(myvars.begin(), myvars.end(), 0.f);
    const std::size_t Nx = myvars.size();
    const std::size_t inputBytes = Nx * sizeof(double);

    try
    {
        /** ADIOS class factory of IO class objects, DebugON is recommended */
        adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON);

        // Get a Transform of type SZ
        adios2::Operator &adiosSZ =
            adios.DefineOperator("SZVariableCompressor", "SZ");

        /*** IO class object: settings and factory of Settings: Variables,
         * Parameters, Transports, and Execution: Engines */
        adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N_SZ");

        /** global array : name, { shape (total) }, { start (local) }, { count
         * (local) }, all are constant dimensions */
        adios2::Variable<double> &var = bpIO.DefineVariable<double>(
            "var", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims);

        // 1st way: adding transform metadata to variable to Engine can decide:
        // &adiosSZ gets mapped to bpUInts.TransformInfo[SZID].Operator
        const unsigned int SZID = var.AddTransform(adiosSZ, {{"foo", "0.01"}});

        // 2nd way: treat Transforms as wrappers to underlying library.
        // you can redefine parameters
        const std::size_t estimatedSize =
            adiosSZ.BufferMaxSize(Nx * var.m_ElementSize);
        std::vector<char> compressedBuffer(estimatedSize);
        size_t compressedSize = adiosSZ.Compress(
            myvars.data(), var.m_Count, var.m_ElementSize, var.m_Type,
            compressedBuffer.data(), {{"accuracy", "0.01"}});

        compressedBuffer.resize(compressedSize);

        std::cout << "Rank " << rank << "\n";
        std::cout << "Compression summary:\n";
        std::cout << "Input data size: " << inputBytes << " bytes\n";
        std::cout << "SZ estimated output size: " << estimatedSize
                  << " bytes\n";
        std::cout << "SZ final output size: " << compressedSize << " bytes\n\n";

        // Allocate original data size
        std::vector<double> decompressedBuffer(Nx);
        size_t decompressedSize = adiosSZ.Decompress(
            compressedBuffer.data(), compressedSize, decompressedBuffer.data(),
            var.m_Count, var.m_Type, var.m_OperatorsInfo[SZID].Parameters);

        std::cout << "Decompression summary:\n";
        std::cout << "Decompressed size: " << decompressedSize << " bytes\n";
        std::cout << "Data:\n";

        for (int i = 0; i < decompressedBuffer.size(); i++)
        {
            if (i % 25 == 0)
            {
                std::cout << "\n";
            }
            std::cout << decompressedBuffer[i] << " ";
        }
        std::cout << "\n";
    }
    catch (std::invalid_argument &e)
    {
        std::cout << "Invalid argument exception, STOPPING PROGRAM from rank "
                  << rank << "\n";
        std::cout << e.what() << "\n";
    }
    catch (std::ios_base::failure &e)
    {
        std::cout
            << "IO System base failure exception, STOPPING PROGRAM from rank "
            << rank << "\n";
        std::cout << e.what() << "\n";
    }
    catch (std::exception &e)
    {
        std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n";
        std::cout << e.what() << "\n";
    }

    MPI_Finalize();

    return 0;
}
<|endoftext|>


<commit_before>#include <glad.h>
#include <glfw3.h>

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";

int main()
{
	// glfw: initialize and configure
	// ------------------------------
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif

														 // glfw window creation
														 // --------------------
	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	// glad: load all OpenGL function pointers
	// ---------------------------------------
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	// build and compile our shader program
	// ------------------------------------
	// vertex shader
	int vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);
	// check for shader compile errors
	int success;
	char infoLog[512];
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
	}
	// fragment shader
	int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);
	// check for shader compile errors
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
	}
	// link shaders
	int shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);
	// check for linking errors
	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	// set up vertex data (and buffer(s)) and configure vertex attributes
	// ------------------------------------------------------------------
	float vertices1[] = {
		-0.75f,	-0.25f,	0.0f, //bottom left
		-0.25f,	-0.25f,	0.0f, //middle left
		-0.5f,	0.5f,	0.0f, //top left
	};
	float vertices2[] ={
		0.5f,	0.5f,	0.0f, //top right
		0.25f,	-0.25f,	0.0f, //middle right
		0.75f,	-0.25f,	0.0f //bottom right
	};
	unsigned int VBO1, VBO2, VAO1, VAO2;
	glGenVertexArrays(1, &VAO1);
	glGenBuffers(1, &VBO1);
	// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
	glBindVertexArray(VAO1);

	glBindBuffer(GL_ARRAY_BUFFER, VBO1);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
	//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	glGenVertexArrays(1, &VAO2);
	glGenBuffers(1, &VBO2);
	// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
	glBindVertexArray(VAO2);

	glBindBuffer(GL_ARRAY_BUFFER, VBO2);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
	//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
	// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
	glBindVertexArray(0);

	// uncomment this call to draw in wireframe polygons.
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	// render loop
	// -----------
	while (!glfwWindowShouldClose(window))
	{
		// input
		// -----
		processInput(window);

		// render
		// ------
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		// draw our first triangle
		glUseProgram(shaderProgram);
		//triangle 1
		glBindVertexArray(VAO1);
		glDrawArrays(GL_TRIANGLES, 0, 3);
		//triangle 2
		glBindVertexArray(VAO2);
		glDrawArrays(GL_TRIANGLES, 0, 3);

		// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
		// -------------------------------------------------------------------------------
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	// optional: de-allocate all resources once they've outlived their purpose:
	// ------------------------------------------------------------------------
	glDeleteVertexArrays(1, &VAO1);
	glDeleteVertexArrays(1, &VAO2);
	glDeleteBuffers(1, &VBO1);
	glDeleteBuffers(1, &VBO2);

	// glfw: terminate, clearing all previously allocated GLFW resources.
	// ------------------------------------------------------------------
	glfwTerminate();
	return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	// make sure the viewport matches the new window dimensions; note that width and
	// height will be significantly larger than specified on retina displays.
	glViewport(0, 0, width, height);
}<commit_msg>Colored triangles using 2 shaders - orange and yellow<commit_after>#include <glad.h>
#include <glfw3.h>

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShader1Source = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
const char *fragmentShader2Source = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n"
"}\n\0";

int main()
{
	// glfw: initialize and configure
	// ------------------------------
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
#endif

														 // glfw window creation
														 // --------------------
	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	// glad: load all OpenGL function pointers
	// ---------------------------------------
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	// build and compile our shader program
	// ------------------------------------
	// vertex shader
	int vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);
	// check for shader compile errors
	int success;
	char infoLog[512];
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
	}
	// fragment shader orange
	int fragmentShaderOrange = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShaderOrange, 1, &fragmentShader1Source, NULL);
	glCompileShader(fragmentShaderOrange);
	// check for shader compile errors
	glGetShaderiv(fragmentShaderOrange, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(fragmentShaderOrange, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
	}
	// fragment shader yellow
	int fragmentShaderYellow = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShaderYellow, 1, &fragmentShader2Source, NULL);
	glCompileShader(fragmentShaderYellow);
	// check for shader compile errors
	glGetShaderiv(fragmentShaderYellow, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(fragmentShaderYellow, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
	}
	// link shaders
	//create orange shaderprogram
	int shaderProgramOrange = glCreateProgram();
	glAttachShader(shaderProgramOrange, vertexShader);
	glAttachShader(shaderProgramOrange, fragmentShaderOrange);
	glLinkProgram(shaderProgramOrange);
	glGetProgramiv(shaderProgramOrange, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(shaderProgramOrange, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}

	//create yellow shaderprogram
	int shaderProgramYellow = glCreateProgram();
	glAttachShader(shaderProgramYellow, vertexShader);
	glAttachShader(shaderProgramYellow, fragmentShaderYellow);
	glLinkProgram(shaderProgramYellow);
	// check for linking errors
	glGetProgramiv(shaderProgramYellow, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(shaderProgramYellow, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}
	//Remove shaders since they're already in program
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShaderOrange);
	glDeleteShader(fragmentShaderYellow);

	// set up vertex data (and buffer(s)) and configure vertex attributes
	// ------------------------------------------------------------------
	float vertices1[] = {
		-0.75f,	-0.25f,	0.0f, //bottom left
		-0.25f,	-0.25f,	0.0f, //middle left
		-0.5f,	0.5f,	0.0f, //top left
	};
	float vertices2[] ={
		0.5f,	0.5f,	0.0f, //top right
		0.25f,	-0.25f,	0.0f, //middle right
		0.75f,	-0.25f,	0.0f //bottom right
	};
	unsigned int VBO1, VBO2, VAO1, VAO2;
	glGenVertexArrays(1, &VAO1);
	glGenBuffers(1, &VBO1);
	// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
	glBindVertexArray(VAO1);

	glBindBuffer(GL_ARRAY_BUFFER, VBO1);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
	//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	glGenVertexArrays(1, &VAO2);
	glGenBuffers(1, &VBO2);
	// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
	glBindVertexArray(VAO2);

	glBindBuffer(GL_ARRAY_BUFFER, VBO2);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
	//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
	// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
	glBindVertexArray(0);

	// uncomment this call to draw in wireframe polygons.
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	// render loop
	// -----------
	while (!glfwWindowShouldClose(window))
	{
		// input
		// -----
		processInput(window);

		// render
		// ------
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		// draw our first triangle
		glUseProgram(shaderProgramOrange);
		//triangle 1
		glBindVertexArray(VAO1);
		glDrawArrays(GL_TRIANGLES, 0, 3);
		//triangle 2
		glUseProgram(shaderProgramYellow);
		glBindVertexArray(VAO2);
		glDrawArrays(GL_TRIANGLES, 0, 3);

		// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
		// -------------------------------------------------------------------------------
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	// optional: de-allocate all resources once they've outlived their purpose:
	// ------------------------------------------------------------------------
	glDeleteVertexArrays(1, &VAO1);
	glDeleteVertexArrays(1, &VAO2);
	glDeleteBuffers(1, &VBO1);
	glDeleteBuffers(1, &VBO2);

	// glfw: terminate, clearing all previously allocated GLFW resources.
	// ------------------------------------------------------------------
	glfwTerminate();
	return 0;
}

// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}

// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	// make sure the viewport matches the new window dimensions; note that width and
	// height will be significantly larger than specified on retina displays.
	glViewport(0, 0, width, height);
}<|endoftext|>


<commit_before>// Time:  O((|E| + |V|) * log|V|) = O(|E| * log|V|)
// Space: O(|E| + |V|)

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
        using P = pair<int, int>;
        unordered_map<int, vector<P>> adj;
        for (const auto& flight : flights) {
            int u, v, w;
            tie(u, v, w) = make_tuple(flight[0], flight[1], flight[2]);
            adj[u].emplace_back(v, w);
        }

        using T = tuple<int, int, int>;
        priority_queue<T, vector<T>, greater<T>> min_heap;
        min_heap.emplace(0, src, K + 1);
        while (!min_heap.empty()) {
            int result, u, k;
            tie(result, u, k) = min_heap.top(); min_heap.pop();
            if (u == dst) {
                return result;
            }
            if (k > 0) {
                for (const auto& kvp : adj[u]) {
                    int v, w;
                    tie(v, w) = kvp;
                    min_heap.emplace(result + w, v, k - 1);
                }
            }
        }
        return -1;
    }
};
<commit_msg>Update cheapest-flights-within-k-stops.cpp<commit_after>// Time:  O((|E| + |V|) * log|V|) = O(|E| * log|V|)
// Space: O(|E| + |V|) = O(|E|)

class Solution {
public:
    int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
        using P = pair<int, int>;
        unordered_map<int, vector<P>> adj;
        for (const auto& flight : flights) {
            int u, v, w;
            tie(u, v, w) = make_tuple(flight[0], flight[1], flight[2]);
            adj[u].emplace_back(v, w);
        }

        using T = tuple<int, int, int>;
        priority_queue<T, vector<T>, greater<T>> min_heap;
        min_heap.emplace(0, src, K + 1);
        while (!min_heap.empty()) {
            int result, u, k;
            tie(result, u, k) = min_heap.top(); min_heap.pop();
            if (u == dst) {
                return result;
            }
            if (k > 0) {
                for (const auto& kvp : adj[u]) {
                    int v, w;
                    tie(v, w) = kvp;
                    min_heap.emplace(result + w, v, k - 1);
                }
            }
        }
        return -1;
    }
};
<|endoftext|>


<commit_before>//
//  LinkQueue.cpp
//  DataStruct
//
//  Created by guyuexing on 2017/6/8.
//  Copyright © 2017年 neu. All rights reserved.
//

#include "LinkQueue.hpp"

Status InitQueue(LinkQueue &Q){
    //初始化一个头结点，队头和队尾均指向头结点
    if (!(Q.rear=Q.front=(QueuePtr)malloc(sizeof(QNode)))) {
        exit(OVERFLOWD);
    }
    Q.front->next = NULL;
    return OK;
}

Status DestoryQueue(LinkQueue &Q){
    while (Q.front) {
        Q.rear = Q.front->next; //修改队尾指针指向头结点的下一个结点
        free(Q.front); //第一次是释放头结点
        Q.front = Q.rear;
    }
    return OK;
}

Status ClearQueue(LinkQueue &Q){
    QueuePtr p,q;
    p = Q.front->next; //p指向头结点的下一个结点
    while (p) { //释放除头结点之外的其他结点
        q = p;
        p = p->next;
        free(q);
    }
    Q.front->next = NULL;
    Q.rear = Q.front;
    return OK;
}

Status QueueEmpty(LinkQueue Q){
    return Q.front == Q.rear;
}

int QueueLength(LinkQueue Q){
    int length = 0;
    QueuePtr p = Q.front->next;
    while (p) {
        p=p->next;
        length++;
    }
    return length;
}

//若队列不空，用e返回队列的队头元素
Status GerHead(LinkQueue Q, QElemType &e){
    if (Q.front==Q.rear) { //如果队列为空
        return ERROR;
    }
    e = Q.front->next->data;
    return OK;
}

//插入队尾
Status EnQueue(LinkQueue &Q,QElemType e){
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if (!p) {
        exit(OVERFLOW); //分配存储失败
    }
    p->data = e;
    Q.rear->next = p;
    p->next = NULL;
    Q.rear = p;
    return OK;
}

//删除队头
Status DeQueue(LinkQueue &Q, QElemType &e){
    if (Q.front == Q.rear) {
        return ERROR;
    }
    QueuePtr p = Q.front->next;
    Q.front->next = p->next;
    e = p->data;
    if (Q.rear == p) {  //如果要删除的p是队列的最后一个结点，修改队尾指针
        Q.rear = Q.front;
    }
    free(p);
    return OK;
}

//从队头到队尾依次对Q的每个数据元素调用visit函数
Status QueueTraverse(LinkQueue &Q, void *visit(QElemType)){
    QueuePtr p = Q.front->next;
    while (p) {
        visit(p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
}
<commit_msg>对链队列的部分操作方法加入注释<commit_after>//
//  LinkQueue.cpp
//  DataStruct
//
//  Created by guyuexing on 2017/6/8.
//  Copyright © 2017年 neu. All rights reserved.
//

#include "LinkQueue.hpp"

Status InitQueue(LinkQueue &Q){
    //初始化一个头结点，队头和队尾均指向头结点
    if (!(Q.rear=Q.front=(QueuePtr)malloc(sizeof(QNode)))) {
        exit(OVERFLOWD);
    }
    Q.front->next = NULL;
    return OK;
}

Status DestoryQueue(LinkQueue &Q){
    while (Q.front) {
        Q.rear = Q.front->next; //修改队尾指针指向头结点的下一个结点
        free(Q.front); //第一次是释放头结点
        Q.front = Q.rear;
    }
    return OK;
}

//清空队列只是清空队列中的元素，但是队列的头结点还是需要保留
Status ClearQueue(LinkQueue &Q){
    QueuePtr p,q;
    p = Q.front->next; //p指向头结点的下一个结点
    while (p) { //释放除头结点之外的其他结点
        q = p;
        p = p->next;
        free(q);
    }
    Q.front->next = NULL;
    Q.rear = Q.front;
    return OK;
}

Status QueueEmpty(LinkQueue Q){
    return Q.front == Q.rear;
}

int QueueLength(LinkQueue Q){
    int length = 0;
    QueuePtr p = Q.front->next;
    while (p) {
        p=p->next;
        length++;
    }
    return length;
}

//若队列不空，用e返回队列的队头元素
Status GerHead(LinkQueue Q, QElemType &e){
    if (Q.front==Q.rear) { //如果队列为空
        return ERROR;
    }
    e = Q.front->next->data;
    return OK;
}

//插入队尾,对于链式的存储结构，队列的尾指针指向最后一个元素
Status EnQueue(LinkQueue &Q,QElemType e){
    QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
    if (!p) {
        exit(OVERFLOW); //分配存储失败
    }
    p->data = e;
    Q.rear->next = p;
    p->next = NULL;
    Q.rear = p;
    return OK;
}

//删除队头
Status DeQueue(LinkQueue &Q, QElemType &e){
    if (Q.front == Q.rear) {
        return ERROR;
    }
    QueuePtr p = Q.front->next;
    Q.front->next = p->next;
    e = p->data;
    if (Q.rear == p) {  //如果要删除的p是队列的最后一个结点，修改队尾指针
        Q.rear = Q.front;
    }
    free(p);
    return OK;
}

//从队头到队尾依次对Q的每个数据元素调用visit函数
Status QueueTraverse(LinkQueue &Q, void *visit(QElemType)){
    QueuePtr p = Q.front->next;
    while (p) {
        visit(p->data);
        p = p->next;
    }
    printf("\n");
    return OK;
}
<|endoftext|>


<commit_before>/*
 * File:   DebugServer.cpp
 * Author: thomas
 *
 * Created on 10. September 2010, 15:38
 */

#include <string>
#include <stdlib.h>

#include <iostream>
#include <string.h>

#include "DebugServer.h"

DebugServer::DebugServer()
: comm(5401)
{

  commands = g_async_queue_new();
  answers = g_async_queue_new();

  if(g_thread_supported())
  {
    GError* err = NULL;
    g_message("Starting debug server as seperate thread");
    dispatcherThread = g_thread_create(dispatcher_static, this, true, &err);

  }
  else
  {
    g_warning("No threading support: DebugServer not available");
  }

}

void DebugServer::dispatcher()
{
  g_message("Dispatcher init");
  g_async_queue_ref(commands);
  g_async_queue_ref(answers);
  comm.init();

  g_message("Starting DebugServer dispatcher loop");
  while(true)
  {
    char* msg = comm.readMessage();
    if(msg != NULL)
    {
      g_async_queue_push(commands, msg);
    }

    while(g_async_queue_length(answers) > 0)
    {
      g_debug("there is something in the *answer* queue");
      char* answer = (char*) g_async_queue_pop(answers);

      g_debug("found %s in the *answer* queue", answer);

      comm.sendMessage(answer, strlen(answer)+1);

      delete answer;
    }

    g_thread_yield();
  }

}

void DebugServer::execute()
{
  g_debug("DebugServer::execute");
  if(g_async_queue_length(commands) > 0)
  {
    g_debug("there is something in the *commands* queue");
    char* cmdRaw = (char*) g_async_queue_pop(commands);

    g_debug("found %s in the *commands* queue", cmdRaw);

    GString* answer = g_string_new("");
    g_string_append(answer, "not implemented: ");
    g_string_append(answer, cmdRaw);
    g_string_append(answer, "\n\0");

    g_async_queue_push(answers, g_string_free(answer,false));
    g_debug("pushed new answer");

    delete cmdRaw;
  }
}

void* DebugServer::dispatcher_static(void* ref)
{
  ((DebugServer*) ref)->dispatcher();
  return NULL;
}

DebugServer::~DebugServer()
{
  g_free(dispatcherThread);
  g_async_queue_unref(commands);
  g_async_queue_unref(answers);
}

<commit_msg>yielding more often<commit_after>/*
 * File:   DebugServer.cpp
 * Author: thomas
 *
 * Created on 10. September 2010, 15:38
 */

#include <string>
#include <stdlib.h>

#include <iostream>
#include <string.h>

#include "DebugServer.h"

DebugServer::DebugServer()
: comm(5401)
{

  commands = g_async_queue_new();
  answers = g_async_queue_new();

  if(g_thread_supported())
  {
    GError* err = NULL;
    g_message("Starting debug server as seperate thread");
    dispatcherThread = g_thread_create(dispatcher_static, this, true, &err);

  }
  else
  {
    g_warning("No threading support: DebugServer not available");
  }

}

void DebugServer::dispatcher()
{
  g_message("Dispatcher init");
  g_async_queue_ref(commands);
  g_async_queue_ref(answers);
  comm.init();

  g_message("Starting DebugServer dispatcher loop");
  while(true)
  {
    char* msg = comm.readMessage();
    if(msg != NULL)
    {
      g_async_queue_push(commands, msg);
    }

    g_thread_yield();

    while(g_async_queue_length(answers) > 0)
    {
      g_debug("there is something in the *answer* queue");
      char* answer = (char*) g_async_queue_pop(answers);

      g_debug("found %s in the *answer* queue", answer);

      comm.sendMessage(answer, strlen(answer)+1);

      delete answer;
      g_thread_yield();
    }

    g_thread_yield();
  }

}

void DebugServer::execute()
{
  g_debug("DebugServer::execute");
  if(g_async_queue_length(commands) > 0)
  {
    g_debug("there is something in the *commands* queue");
    char* cmdRaw = (char*) g_async_queue_pop(commands);

    g_debug("found %s in the *commands* queue", cmdRaw);

    GString* answer = g_string_new("");
    g_string_append(answer, "not implemented: ");
    g_string_append(answer, cmdRaw);
    g_string_append(answer, "\n\0");

    g_async_queue_push(answers, g_string_free(answer,false));
    g_debug("pushed new answer");

    delete cmdRaw;
  }
}

void* DebugServer::dispatcher_static(void* ref)
{
  ((DebugServer*) ref)->dispatcher();
  return NULL;
}

DebugServer::~DebugServer()
{
  g_free(dispatcherThread);
  g_async_queue_unref(commands);
  g_async_queue_unref(answers);
}

<|endoftext|>


<commit_before>#include <vector>

#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/utility.hpp>

#include <vigra/numpy_array.hxx>
#include <vigra/numpy_array_converters.hxx>
#include <vigra/multi_array.hxx>

#include "../include/pgmlink/traxels.h"

using namespace pgmlink;
using namespace boost::python;

namespace pgmlink {
  using namespace std;
  using namespace vigra;

  // extending Traxel
  void set_intmaxpos_locator(Traxel& t) {
    Locator* l = new IntmaxposLocator();
    t.set_locator(l); // takes ownership of pointer
  }

  void set_x_scale(Traxel& t, double s) {
    t.locator()->x_scale = s;
  }
  void set_y_scale(Traxel& t, double s) {
    t.locator()->y_scale = s;
  }
  void set_z_scale(Traxel& t, double s) {
    t.locator()->z_scale = s;
  }

  void add_feature_array(Traxel& t, string key, size_t size) {
    t.features[key] = feature_array(size, 0);
  }

  float get_feature_value(Traxel& t, string key, MultiArrayIndex i) {
    FeatureMap::const_iterator it = t.features.find(key);
    if(it == t.features.end()) {
      throw std::runtime_error("key not present in feature map");
    }
    if( !(static_cast<size_t>(i) < it->second.size())) {
      throw std::runtime_error("index out of range");
    }

    return it->second[i];
  }

  void set_feature_value(Traxel& t, string key, MultiArrayIndex i, float value) {
    FeatureMap::iterator it = t.features.find(key);
    if(it == t.features.end()) {
      throw std::runtime_error("key not present in feature map");
    }
    if( !(static_cast<size_t>(i) < it->second.size())) {
      throw std::runtime_error("index out of range");
    }
    it->second[i] = value;
  }

  // extending Traxels
  void add_traxel(Traxels& ts, const Traxel& t) {
    ts[t.Id] = t;
  }

  // extending TraxelStore
  void add_traxel_to_traxelstore(TraxelStore& ts, const Traxel& t) {
    add(ts, t);
  }

  void add_Traxels_to_traxelstore(TraxelStore& ts, const Traxels& traxels) {
    for(Traxels::const_iterator it = traxels.begin(); it!= traxels.end(); ++it){
      add(ts, it->second);
    }
  }

} /* namespace pgmlink */

void export_traxels() {
    class_< feature_array >("feature_array");

    class_< ComLocator >("ComLocator")
      .def_readwrite("x_scale", &ComLocator::x_scale)
      .def_readwrite("y_scale", &ComLocator::y_scale)
      .def_readwrite("z_scale", &ComLocator::z_scale)
    ;

    class_< IntmaxposLocator >("IntmaxposLocator")
      .def_readwrite("x_scale", &ComLocator::x_scale)
      .def_readwrite("y_scale", &ComLocator::y_scale)
      .def_readwrite("z_scale", &ComLocator::z_scale)
    ;

    class_< std::map<std::string,feature_array> >("FeatureMap")
	.def(map_indexing_suite<std::map<std::string,feature_array> >())
    ;
    class_<Traxel>("Traxel")
	.def_readwrite("Id", &Traxel::Id)
	.def_readwrite("Timestep", &Traxel::Timestep)
        //.def("set_locator", &Traxel::set_locator, return_self<>())
        .def("set_x_scale", &set_x_scale)
        .def("set_y_scale", &set_y_scale)
        .def("set_z_scale", &set_z_scale)
        .def("set_intmaxpos_locator", &set_intmaxpos_locator, args("self"))
        .def("X", &Traxel::X)
        .def("Y", &Traxel::Y)
        .def("Z", &Traxel::Z)
	.def_readwrite("features", &Traxel::features)
        .def("add_feature_array", &add_feature_array, args("self","name", "size"), "Add a new feature array to the features map; initialize with zeros. If the name is already present, the old feature array will be replaced.")
	.def("get_feature_value", &get_feature_value, args("self", "name", "index"))
	.def("set_feature_value", &set_feature_value, args("self", "name", "index", "value"))
    ;

    class_<map<unsigned int, Traxel> >("Traxels")
	.def("add_traxel", &add_traxel)
	.def("__len__", &Traxels::size)
    ;

    class_< std::vector<double> >("VectorOfDouble")
    .def(vector_indexing_suite< std::vector<double> >() )
    ;

    class_<TraxelStore>("TraxelStore")
      .def("add", &add_traxel_to_traxelstore)
      .def("add_from_Traxels", &add_Traxels_to_traxelstore)
      .def("bounding_box", &bounding_box)
      ;
}
<commit_msg>pytraxels: added VectorOfInt<commit_after>#include <vector>

#include <boost/python.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/utility.hpp>

#include <vigra/numpy_array.hxx>
#include <vigra/numpy_array_converters.hxx>
#include <vigra/multi_array.hxx>

#include "../include/pgmlink/traxels.h"

using namespace pgmlink;
using namespace boost::python;

namespace pgmlink {
  using namespace std;
  using namespace vigra;

  // extending Traxel
  void set_intmaxpos_locator(Traxel& t) {
    Locator* l = new IntmaxposLocator();
    t.set_locator(l); // takes ownership of pointer
  }

  void set_x_scale(Traxel& t, double s) {
    t.locator()->x_scale = s;
  }
  void set_y_scale(Traxel& t, double s) {
    t.locator()->y_scale = s;
  }
  void set_z_scale(Traxel& t, double s) {
    t.locator()->z_scale = s;
  }

  void add_feature_array(Traxel& t, string key, size_t size) {
    t.features[key] = feature_array(size, 0);
  }

  float get_feature_value(Traxel& t, string key, MultiArrayIndex i) {
    FeatureMap::const_iterator it = t.features.find(key);
    if(it == t.features.end()) {
      throw std::runtime_error("key not present in feature map");
    }
    if( !(static_cast<size_t>(i) < it->second.size())) {
      throw std::runtime_error("index out of range");
    }

    return it->second[i];
  }

  void set_feature_value(Traxel& t, string key, MultiArrayIndex i, float value) {
    FeatureMap::iterator it = t.features.find(key);
    if(it == t.features.end()) {
      throw std::runtime_error("key not present in feature map");
    }
    if( !(static_cast<size_t>(i) < it->second.size())) {
      throw std::runtime_error("index out of range");
    }
    it->second[i] = value;
  }

  // extending Traxels
  void add_traxel(Traxels& ts, const Traxel& t) {
    ts[t.Id] = t;
  }

  // extending TraxelStore
  void add_traxel_to_traxelstore(TraxelStore& ts, const Traxel& t) {
    add(ts, t);
  }

  void add_Traxels_to_traxelstore(TraxelStore& ts, const Traxels& traxels) {
    for(Traxels::const_iterator it = traxels.begin(); it!= traxels.end(); ++it){
      add(ts, it->second);
    }
  }

} /* namespace pgmlink */

void export_traxels() {
    class_< feature_array >("feature_array");

    class_< ComLocator >("ComLocator")
      .def_readwrite("x_scale", &ComLocator::x_scale)
      .def_readwrite("y_scale", &ComLocator::y_scale)
      .def_readwrite("z_scale", &ComLocator::z_scale)
    ;

    class_< IntmaxposLocator >("IntmaxposLocator")
      .def_readwrite("x_scale", &ComLocator::x_scale)
      .def_readwrite("y_scale", &ComLocator::y_scale)
      .def_readwrite("z_scale", &ComLocator::z_scale)
    ;

    class_< std::map<std::string,feature_array> >("FeatureMap")
	.def(map_indexing_suite<std::map<std::string,feature_array> >())
    ;
    class_<Traxel>("Traxel")
	.def_readwrite("Id", &Traxel::Id)
	.def_readwrite("Timestep", &Traxel::Timestep)
        //.def("set_locator", &Traxel::set_locator, return_self<>())
        .def("set_x_scale", &set_x_scale)
        .def("set_y_scale", &set_y_scale)
        .def("set_z_scale", &set_z_scale)
        .def("set_intmaxpos_locator", &set_intmaxpos_locator, args("self"))
        .def("X", &Traxel::X)
        .def("Y", &Traxel::Y)
        .def("Z", &Traxel::Z)
	.def_readwrite("features", &Traxel::features)
        .def("add_feature_array", &add_feature_array, args("self","name", "size"), "Add a new feature array to the features map; initialize with zeros. If the name is already present, the old feature array will be replaced.")
	.def("get_feature_value", &get_feature_value, args("self", "name", "index"))
	.def("set_feature_value", &set_feature_value, args("self", "name", "index", "value"))
    ;

    class_<map<unsigned int, Traxel> >("Traxels")
	.def("add_traxel", &add_traxel)
	.def("__len__", &Traxels::size)
    ;

    class_< std::vector<double> >("VectorOfDouble")
      .def(vector_indexing_suite< std::vector<double> >() )
    ;

    class_< std::vector<int> >("VectorOfInt")
      .def(vector_indexing_suite< std::vector<int> >() )
    ;

    class_<TraxelStore>("TraxelStore")
      .def("add", &add_traxel_to_traxelstore)
      .def("add_from_Traxels", &add_Traxels_to_traxelstore)
      .def("bounding_box", &bounding_box)
      ;
}
<|endoftext|>


<commit_before>/*
  Q Light Controller Plus
  mainview2d.cpp

  Copyright (c) Massimo Callegari

  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.txt

  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 <QDebug>
#include <QQuickItem>
#include <QQmlContext>
#include <QQmlComponent>

#include "mainview2d.h"
#include "qlcfixturemode.h"
#include "doc.h"

MainView2D::MainView2D(QQuickView *view, Doc *doc, QObject *parent)
    : PreviewContext(view, doc, parent)
{
    m_gridSize = QSize(5, 5);
    m_gridScale = 1.0;
    m_cellPixels = 100;
    m_xOffset = 0;
    m_yOffset = 0;
    m_gridUnits = 1000;

    m_view2D = NULL;
    m_contents2D = NULL;

    fixtureComponent = new QQmlComponent(m_view->engine(), QUrl("qrc:/Fixture2DItem.qml"));
    if (fixtureComponent->isError())
        qDebug() << fixtureComponent->errors();

    connect(m_doc, SIGNAL(loaded()),
            this, SLOT(slotRefreshView()));
}

MainView2D::~MainView2D()
{
    resetItems();
}

void MainView2D::enableContext(bool enable)
{
    PreviewContext::enableContext(enable);
    if (enable == true)
        slotRefreshView();
}

void MainView2D::resetItems()
{
    QMapIterator<quint32, QQuickItem*> it(m_itemsMap);
    while(it.hasNext())
    {
        it.next();
        delete it.value();
    }
    m_itemsMap.clear();
}

void MainView2D::initialize2DProperties()
{
    m_view2D = qobject_cast<QQuickItem*>(m_view->rootObject()->findChild<QObject *>("twoDView"));
    m_contents2D = qobject_cast<QQuickItem*>(m_view->rootObject()->findChild<QObject *>("twoDContents"));

    if (m_view2D == NULL || m_contents2D == NULL)
        return;

    m_gridScale = m_view2D->property("gridScale").toReal();
    m_cellPixels = m_view2D->property("baseCellSize").toReal();

    m_xOffset = m_contents2D->property("x").toReal();
    m_yOffset = m_contents2D->property("y").toReal();
}

QPointF MainView2D::getAvailablePosition(QRectF& fxRect)
{
    qreal xPos = fxRect.x(), yPos = fxRect.y();
    qreal maxYOffset = 0;

    if (m_view2D == NULL || m_contents2D == NULL)
        initialize2DProperties();

    QRectF gridArea(0, 0, m_gridSize.width() * m_gridUnits, m_gridSize.height() * m_gridUnits);

    qreal origWidth = fxRect.width();
    qreal origHeight = fxRect.height();

    QMapIterator<quint32, QQuickItem *> it(m_itemsMap);
    while (it.hasNext())
    {
        it.next();
        QQuickItem *fxItem = it.value();
        qreal itemXPos = fxItem->property("mmXPos").toReal();
        qreal itemYPos = fxItem->property("mmYPos").toReal();
        qreal itemWidth = fxItem->property("mmWidth").toReal();
        qreal itemHeight = fxItem->property("mmHeight").toReal();

        // store the next Y row in case we need to lower down
        if (itemYPos + itemHeight > maxYOffset )
            maxYOffset = itemYPos + itemHeight;

        QRectF itemRect(itemXPos, itemYPos, itemWidth, itemHeight);

        if (fxRect.intersects(itemRect) == true)
        {
            xPos = itemXPos + itemWidth + 50; //add an extra 50mm spacing
            if (xPos + fxRect.width() > gridArea.width())
            {
                xPos = 0;
                yPos = maxYOffset + 50;
                maxYOffset = 0;
            }
            fxRect.setX(xPos);
            fxRect.setY(yPos);
            // restore width and height as setX and setY mess them
            fxRect.setWidth(origWidth);
            fxRect.setHeight(origHeight);
        }
        else
            break;
    }

    return QPointF(xPos, yPos);
}

void MainView2D::createFixtureItem(quint32 fxID, qreal x, qreal y, bool mmCoords)
{
    if (isEnabled() == false)
        return;

    //if (m_view2D == NULL || m_contents2D == NULL)
        initialize2DProperties();

    qDebug() << "[MainView2D] Creating fixture with ID" << fxID << "x:" << x << "y:" << y;

    Fixture *fixture = m_doc->fixture(fxID);
    MonitorProperties *mProps = m_doc->monitorProperties();
    QLCFixtureMode *fxMode = fixture->fixtureMode();
    QRectF fxRect;

    QQuickItem *newFixtureItem = qobject_cast<QQuickItem*>(fixtureComponent->create());

    newFixtureItem->setParentItem(m_contents2D);
    newFixtureItem->setProperty("fixtureID", fxID);

    if (mmCoords == false)
    {
        if (x == 0 && y == 0)
        {
            x = (m_xOffset * m_gridUnits) / m_cellPixels;
            y = (m_yOffset * m_gridUnits) / m_cellPixels;
        }
        else
        {
            x = ((x - m_xOffset) * m_gridUnits) / m_cellPixels;
            y = ((y - m_yOffset) * m_gridUnits) / m_cellPixels;
        }
    }
    fxRect.setX(x);
    fxRect.setY(y);

    if (fxMode != NULL)
    {
        if (fxMode->physical().width() != 0)
        {
            newFixtureItem->setProperty("mmWidth", fxMode->physical().width());
            fxRect.setWidth(fxMode->physical().width());
        }
        if (fxMode->physical().height() != 0)
        {
            newFixtureItem->setProperty("mmHeight", fxMode->physical().height());
            fxRect.setHeight(fxMode->physical().height());
        }
        qDebug() << "Current mode fixture heads:" << fxMode->heads().count();
        newFixtureItem->setProperty("headsNumber", fxMode->heads().count());
    }
    else
    {
        // default to 300x300mm
        fxRect.setWidth(300);
        fxRect.setHeight(300);
    }

    QPointF availablePos = getAvailablePosition(fxRect);
    x = availablePos.x();
    y = availablePos.y();

    newFixtureItem->setProperty("mmXPos", x);
    newFixtureItem->setProperty("mmYPos", y);
    newFixtureItem->setProperty("fixtureName", fixture->name());

    // add the new fixture to the Doc monitor properties
    mProps->setFixturePosition(fxID, QPointF(x, y));

    // and finally add the new item to the items map
    m_itemsMap[fxID] = newFixtureItem;

    updateFixture(fixture);
}

QList<quint32> MainView2D::selectFixturesRect(QRectF rect)
{
    QList<quint32>fxList;
    QMapIterator<quint32, QQuickItem *> it(m_itemsMap);
    while (it.hasNext())
    {
        it.next();
        QQuickItem *fxItem = it.value();
        qreal itemXPos = fxItem->property("x").toReal();
        qreal itemYPos = fxItem->property("y").toReal();
        qreal itemWidth = fxItem->property("width").toReal();
        qreal itemHeight = fxItem->property("height").toReal();

        QRectF itemRect(itemXPos, itemYPos, itemWidth, itemHeight);

        qDebug() << "Rect:" << rect << "itemRect:" << itemRect;

        if (rect.contains(itemRect))
        {
            if (fxItem->property("isSelected").toBool() == false)
            {
                fxItem->setProperty("isSelected", true);
                fxList.append(it.key());
            }
        }
    }
    return fxList;
}

void MainView2D::slotRefreshView()
{
    if (isEnabled() == false)
        return;

    initialize2DProperties();

    if (m_view2D == NULL || m_contents2D == NULL)
        return;

    MonitorProperties *mProps = m_doc->monitorProperties();
    QList<quint32> mPropsIDs;
    if (mProps)
    {
        mPropsIDs = mProps->fixtureItemsID();
        m_view2D->setProperty("gridWidth", mProps->gridSize().width());
        m_view2D->setProperty("gridHeight", mProps->gridSize().height());
        if (mProps->gridUnits() == MonitorProperties::Meters)
            m_view2D->setProperty("gridUnits", 1000);
        else
            m_view2D->setProperty("gridUnits", 304.8);
    }

    resetItems();

    foreach(Fixture *fixture, m_doc->fixtures())
    {
        if (mPropsIDs.contains(fixture->id()))
        {
            QPointF fxPos = mProps->fixturePosition(fixture->id());
            createFixtureItem(fixture->id(), fxPos.x(), fxPos.y());
        }
        else
            createFixtureItem(fixture->id(), 0, 0, false);
    }
}

void MainView2D::updateFixture(Fixture *fixture)
{
    if (m_enabled == false || fixture == NULL)
        return;

    if (m_itemsMap.contains(fixture->id()) == false)
        return;

    QQuickItem *fxItem = m_itemsMap[fixture->id()];

    for (int headIdx = 0; headIdx < fixture->heads(); headIdx++)
    {
        quint32 mdIndex = fixture->masterIntensityChannel(headIdx);
        qDebug() << "Head" << headIdx << "dimmer channel:" << mdIndex;
        if (mdIndex != QLCChannel::invalid())
        {
            uchar intValue = fixture->channelValueAt(mdIndex);
            QMetaObject::invokeMethod(fxItem, "setHeadIntensity",
                    Q_ARG(QVariant, headIdx),
                    Q_ARG(QVariant, (qreal)intValue / 255.0));
        }

        QVector <quint32> rgbCh = fixture->rgbChannels(headIdx);
        if (rgbCh.size() > 0)
        {
            quint8 r = 0, g = 0, b = 0;
            r = fixture->channelValueAt(rgbCh.at(0));
            g = fixture->channelValueAt(rgbCh.at(1));
            b = fixture->channelValueAt(rgbCh.at(2));

            QMetaObject::invokeMethod(fxItem, "setHeadColor",
                    Q_ARG(QVariant, headIdx),
                    Q_ARG(QVariant, QColor(r, g, b)));
        }
    }
}

<commit_msg>QMLUI: set the default size of a new fixture in the C++ code<commit_after>/*
  Q Light Controller Plus
  mainview2d.cpp

  Copyright (c) Massimo Callegari

  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.txt

  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 <QDebug>
#include <QQuickItem>
#include <QQmlContext>
#include <QQmlComponent>

#include "mainview2d.h"
#include "qlcfixturemode.h"
#include "doc.h"

MainView2D::MainView2D(QQuickView *view, Doc *doc, QObject *parent)
    : PreviewContext(view, doc, parent)
{
    m_gridSize = QSize(5, 5);
    m_gridScale = 1.0;
    m_cellPixels = 100;
    m_xOffset = 0;
    m_yOffset = 0;
    m_gridUnits = 1000;

    m_view2D = NULL;
    m_contents2D = NULL;

    fixtureComponent = new QQmlComponent(m_view->engine(), QUrl("qrc:/Fixture2DItem.qml"));
    if (fixtureComponent->isError())
        qDebug() << fixtureComponent->errors();

    connect(m_doc, SIGNAL(loaded()),
            this, SLOT(slotRefreshView()));
}

MainView2D::~MainView2D()
{
    resetItems();
}

void MainView2D::enableContext(bool enable)
{
    PreviewContext::enableContext(enable);
    if (enable == true)
        slotRefreshView();
}

void MainView2D::resetItems()
{
    QMapIterator<quint32, QQuickItem*> it(m_itemsMap);
    while(it.hasNext())
    {
        it.next();
        delete it.value();
    }
    m_itemsMap.clear();
}

void MainView2D::initialize2DProperties()
{
    m_view2D = qobject_cast<QQuickItem*>(m_view->rootObject()->findChild<QObject *>("twoDView"));
    m_contents2D = qobject_cast<QQuickItem*>(m_view->rootObject()->findChild<QObject *>("twoDContents"));

    if (m_view2D == NULL || m_contents2D == NULL)
        return;

    m_gridScale = m_view2D->property("gridScale").toReal();
    m_cellPixels = m_view2D->property("baseCellSize").toReal();

    m_xOffset = m_contents2D->property("x").toReal();
    m_yOffset = m_contents2D->property("y").toReal();
}

QPointF MainView2D::getAvailablePosition(QRectF& fxRect)
{
    qreal xPos = fxRect.x(), yPos = fxRect.y();
    qreal maxYOffset = 0;

    if (m_view2D == NULL || m_contents2D == NULL)
        initialize2DProperties();

    QRectF gridArea(0, 0, m_gridSize.width() * m_gridUnits, m_gridSize.height() * m_gridUnits);

    qreal origWidth = fxRect.width();
    qreal origHeight = fxRect.height();

    QMapIterator<quint32, QQuickItem *> it(m_itemsMap);
    while (it.hasNext())
    {
        it.next();
        QQuickItem *fxItem = it.value();
        qreal itemXPos = fxItem->property("mmXPos").toReal();
        qreal itemYPos = fxItem->property("mmYPos").toReal();
        qreal itemWidth = fxItem->property("mmWidth").toReal();
        qreal itemHeight = fxItem->property("mmHeight").toReal();

        // store the next Y row in case we need to lower down
        if (itemYPos + itemHeight > maxYOffset )
            maxYOffset = itemYPos + itemHeight;

        QRectF itemRect(itemXPos, itemYPos, itemWidth, itemHeight);

        if (fxRect.intersects(itemRect) == true)
        {
            xPos = itemXPos + itemWidth + 50; //add an extra 50mm spacing
            if (xPos + fxRect.width() > gridArea.width())
            {
                xPos = 0;
                yPos = maxYOffset + 50;
                maxYOffset = 0;
            }
            fxRect.setX(xPos);
            fxRect.setY(yPos);
            // restore width and height as setX and setY mess them
            fxRect.setWidth(origWidth);
            fxRect.setHeight(origHeight);
        }
        else
            break;
    }

    return QPointF(xPos, yPos);
}

void MainView2D::createFixtureItem(quint32 fxID, qreal x, qreal y, bool mmCoords)
{
    if (isEnabled() == false)
        return;

    //if (m_view2D == NULL || m_contents2D == NULL)
        initialize2DProperties();

    qDebug() << "[MainView2D] Creating fixture with ID" << fxID << "x:" << x << "y:" << y;

    Fixture *fixture = m_doc->fixture(fxID);
    MonitorProperties *mProps = m_doc->monitorProperties();
    QLCFixtureMode *fxMode = fixture->fixtureMode();
    QRectF fxRect;

    QQuickItem *newFixtureItem = qobject_cast<QQuickItem*>(fixtureComponent->create());

    newFixtureItem->setParentItem(m_contents2D);
    newFixtureItem->setProperty("fixtureID", fxID);

    if (mmCoords == false)
    {
        if (x == 0 && y == 0)
        {
            x = (m_xOffset * m_gridUnits) / m_cellPixels;
            y = (m_yOffset * m_gridUnits) / m_cellPixels;
        }
        else
        {
            x = ((x - m_xOffset) * m_gridUnits) / m_cellPixels;
            y = ((y - m_yOffset) * m_gridUnits) / m_cellPixels;
        }
    }
    fxRect.setX(x);
    fxRect.setY(y);

    if (fxMode != NULL)
    {
        if (fxMode->physical().width() != 0)
            fxRect.setWidth(fxMode->physical().width());
        else
            fxRect.setWidth(300);

        if (fxMode->physical().height() != 0)
            fxRect.setHeight(fxMode->physical().height());
        else
            fxRect.setHeight(300);

        qDebug() << "Current mode fixture heads:" << fxMode->heads().count();
        newFixtureItem->setProperty("headsNumber", fxMode->heads().count());
    }
    else
    {
        // default to 300x300mm
        fxRect.setWidth(300);
        fxRect.setHeight(300);
    }

    newFixtureItem->setProperty("mmWidth", fxRect.width());
    newFixtureItem->setProperty("mmHeight", fxRect.height());

    QPointF availablePos = getAvailablePosition(fxRect);
    x = availablePos.x();
    y = availablePos.y();

    newFixtureItem->setProperty("mmXPos", x);
    newFixtureItem->setProperty("mmYPos", y);
    newFixtureItem->setProperty("fixtureName", fixture->name());

    // add the new fixture to the Doc monitor properties
    mProps->setFixturePosition(fxID, QPointF(x, y));

    // and finally add the new item to the items map
    m_itemsMap[fxID] = newFixtureItem;

    updateFixture(fixture);
}

QList<quint32> MainView2D::selectFixturesRect(QRectF rect)
{
    QList<quint32>fxList;
    QMapIterator<quint32, QQuickItem *> it(m_itemsMap);
    while (it.hasNext())
    {
        it.next();
        QQuickItem *fxItem = it.value();
        qreal itemXPos = fxItem->property("x").toReal();
        qreal itemYPos = fxItem->property("y").toReal();
        qreal itemWidth = fxItem->property("width").toReal();
        qreal itemHeight = fxItem->property("height").toReal();

        QRectF itemRect(itemXPos, itemYPos, itemWidth, itemHeight);

        qDebug() << "Rect:" << rect << "itemRect:" << itemRect;

        if (rect.contains(itemRect))
        {
            if (fxItem->property("isSelected").toBool() == false)
            {
                fxItem->setProperty("isSelected", true);
                fxList.append(it.key());
            }
        }
    }
    return fxList;
}

void MainView2D::slotRefreshView()
{
    if (isEnabled() == false)
        return;

    initialize2DProperties();

    if (m_view2D == NULL || m_contents2D == NULL)
        return;

    MonitorProperties *mProps = m_doc->monitorProperties();
    QList<quint32> mPropsIDs;
    if (mProps)
    {
        mPropsIDs = mProps->fixtureItemsID();
        m_view2D->setProperty("gridWidth", mProps->gridSize().width());
        m_view2D->setProperty("gridHeight", mProps->gridSize().height());
        if (mProps->gridUnits() == MonitorProperties::Meters)
            m_view2D->setProperty("gridUnits", 1000);
        else
            m_view2D->setProperty("gridUnits", 304.8);
    }

    resetItems();

    foreach(Fixture *fixture, m_doc->fixtures())
    {
        if (mPropsIDs.contains(fixture->id()))
        {
            QPointF fxPos = mProps->fixturePosition(fixture->id());
            createFixtureItem(fixture->id(), fxPos.x(), fxPos.y());
        }
        else
            createFixtureItem(fixture->id(), 0, 0, false);
    }
}

void MainView2D::updateFixture(Fixture *fixture)
{
    if (m_enabled == false || fixture == NULL)
        return;

    if (m_itemsMap.contains(fixture->id()) == false)
        return;

    QQuickItem *fxItem = m_itemsMap[fixture->id()];

    for (int headIdx = 0; headIdx < fixture->heads(); headIdx++)
    {
        quint32 mdIndex = fixture->masterIntensityChannel(headIdx);
        qDebug() << "Head" << headIdx << "dimmer channel:" << mdIndex;
        if (mdIndex != QLCChannel::invalid())
        {
            uchar intValue = fixture->channelValueAt(mdIndex);
            QMetaObject::invokeMethod(fxItem, "setHeadIntensity",
                    Q_ARG(QVariant, headIdx),
                    Q_ARG(QVariant, (qreal)intValue / 255.0));
        }

        QVector <quint32> rgbCh = fixture->rgbChannels(headIdx);
        if (rgbCh.size() > 0)
        {
            quint8 r = 0, g = 0, b = 0;
            r = fixture->channelValueAt(rgbCh.at(0));
            g = fixture->channelValueAt(rgbCh.at(1));
            b = fixture->channelValueAt(rgbCh.at(2));

            QMetaObject::invokeMethod(fxItem, "setHeadColor",
                    Q_ARG(QVariant, headIdx),
                    Q_ARG(QVariant, QColor(r, g, b)));
        }
    }
}

<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "<WebSig>" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Institute for
 * Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>.
 * The development of this software was partly funded by the European
 * Commission in the <WebSig> project in the ISIS Programme.
 * For more information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * XSEC
 *
 * InteropResolver := Class to resolve key elements into certificates for
 *						merlin-18 interop test
 *
 * $Id$
 *
 */

// XSEC

#include "MerlinFiveInteropResolver.hpp"

#include <xsec/framework/XSECDefs.hpp>
#include <xsec/enc/XSECKeyInfoResolver.hpp>
#include <xsec/dsig/DSIGKeyInfoName.hpp>
#include <xsec/dsig/DSIGKeyInfoX509.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.hpp>
#include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

XERCES_CPP_NAMESPACE_USE

#include <iostream>

#if !defined (HAVE_OPENSSL) && !defined (HAVE_WINCAPI)
#	error Require OpenSSL or Windows Crypto API for the Merlin Resolver
#endif

#if defined (HAVE_OPENSSL)
#	include <openssl/x509.h>
#	include <openssl/pem.h>
#	include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
#	include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
#endif

// --------------------------------------------------------------------------------
//           Strings and keys
// --------------------------------------------------------------------------------

static XMLCh s_bobName[] = {
	chLatin_b,
	chLatin_o,
	chLatin_b,
	chNull
};

static XMLCh s_jobName[] = {
	chLatin_j,
	chLatin_o,
	chLatin_b,
	chNull
};

static XMLCh s_jebName[] = {
	chLatin_j,
	chLatin_e,
	chLatin_b,
	chNull
};

static XMLCh s_jedName[] = {
	chLatin_j,
	chLatin_e,
	chLatin_d,
	chNull
};

static char s_bobKey[] = "abcdefghijklmnopqrstuvwx";
static char s_jobKey[] = "abcdefghijklmnop";
static char s_jebKey[] = "abcdefghijklmnopqrstuvwx";
static char s_jedKey[] = "abcdefghijklmnopqrstuvwxyz012345";

// --------------------------------------------------------------------------------
//           Construct/Destruct
// --------------------------------------------------------------------------------

MerlinFiveInteropResolver::MerlinFiveInteropResolver(const XMLCh * baseURI) {

	if (baseURI != NULL)
		mp_baseURI = XMLString::replicate(baseURI);
	else
		mp_baseURI = NULL;

#if !defined(_WIN32)
	m_fcount = 0;
#endif

}

MerlinFiveInteropResolver::~MerlinFiveInteropResolver() {

	if (mp_baseURI != NULL)
		delete[]mp_baseURI;

}
// --------------------------------------------------------------------------------
//			Utility functions
// --------------------------------------------------------------------------------
#if defined(_WIN32)

void reverseSlash(safeBuffer &path) {

	for (int i = 0; i < strlen(path.rawCharBuffer()); ++i) {

		if (path[i] == '/')
			path[i] = '\\';

	}

}

#endif

XSECCryptoSymmetricKey * MerlinFiveInteropResolver::makeSymmetricKey(XSECCryptoSymmetricKey::SymmetricKeyType type) {

#if defined (HAVE_OPENSSL)

	OpenSSLCryptoSymmetricKey * k;
	k = new OpenSSLCryptoSymmetricKey(type);

	return k;

#else

	WinCAPICryptoSymmetricKey * k;
	k = new WinCAPICryptoSymmetricKey(0, type);

	return k;

#endif

}

BIO * createFileBIO(const XMLCh * baseURI, const char * name) {

	// Open file URI relative to the encrypted file

	BIO * bioFile;
	if ((bioFile = BIO_new(BIO_s_file())) == NULL) {

		return NULL;

	}

	safeBuffer fname;
	fname.sbTranscodeIn(baseURI);
	fname.sbStrcatIn("/");
	fname.sbStrcatIn(name);

#if defined(_WIN32)
	reverseSlash(fname);
#endif

	if (BIO_read_filename(bioFile, fname.rawCharBuffer()) <= 0) {

		return NULL;

	}

	return bioFile;
}

// --------------------------------------------------------------------------------
//           Resolver
// --------------------------------------------------------------------------------

XSECCryptoKey * MerlinFiveInteropResolver::resolveKey(DSIGKeyInfoList * lst) {

	int lstSize = lst->getSize();

	for (int i = 0; i < lstSize; ++i) {

		DSIGKeyInfo * ki = lst->item(i);

		if (ki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_NAME) {

			DSIGKeyInfoName * kn = dynamic_cast<DSIGKeyInfoName *>(ki);

			const XMLCh * name = kn->getKeyName();

			// Check if this is a key we know

			if (strEquals(s_bobName, name)) {
				XSECCryptoSymmetricKey * k =
					XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_CBC_192);
				try {
					k->setKey((unsigned char *) s_bobKey, strlen(s_bobKey));
				} catch (...) {
					delete k;
					throw;
				}
				return k;
			}
			if (strEquals(s_jobName, name)) {
				XSECCryptoSymmetricKey * k =
					XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_ECB_128);
				try {
					k->setKey((unsigned char *) s_jobKey, strlen(s_jobKey));
				} catch(...) {
					delete k;
					throw;
				}
				return k;
			}
			if (strEquals(s_jebName, name)) {
				XSECCryptoSymmetricKey * k =
					XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_ECB_192);
				try {
					k->setKey((unsigned char *) s_jebKey, strlen(s_jebKey));
				} catch(...) {
					delete k;
					throw;
				}
				return k;
			}
			if (strEquals(s_jedName, name)) {
				XSECCryptoSymmetricKey * k =
					XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_ECB_256);
				try {
					k->setKey((unsigned char *) s_jedKey, strlen(s_jedKey));
				} catch(...) {
					delete k;
					throw;
				}
				return k;
			}

		}

		else if (ki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) {

			DSIGKeyInfoX509 * kix = dynamic_cast<DSIGKeyInfoX509 *> (ki);

			XSECCryptoX509 * XCX509 = kix->getCertificateCryptoItem(0);

			if (XCX509 != 0) {
#if defined (HAVE_OPENSSL)

				if (strEquals(XCX509->getProviderName(),DSIGConstants::s_unicodeStrPROVOpenSSL)) {

					OpenSSLCryptoX509 * OSSLX509 = dynamic_cast<OpenSSLCryptoX509 *>(XCX509);
					X509 * x509 = OSSLX509->getOpenSSLX509();

					// Check the serial number
					BIGNUM * bnserial = ASN1_INTEGER_to_BN(x509->cert_info->serialNumber, NULL);
					char * xserial = BN_bn2dec(bnserial);
					BN_free(bnserial);

					BIO * rsaFile = createFileBIO(mp_baseURI, "rsa.p8");
					if (rsaFile == NULL)
						return NULL;

					PKCS8_PRIV_KEY_INFO * p8inf;
					p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(rsaFile, NULL);

					EVP_PKEY * pk = EVP_PKCS82PKEY(p8inf);
					OpenSSLCryptoKeyRSA * k = new OpenSSLCryptoKeyRSA(pk);
					return k;
						//d2i_PKCS8PrivateKey_bio(rsaFile, NULL, NULL, NULL);

/*					if (strcmp(xserial, cserial) == 0) {

						OPENSSL_free(xserial);
						delete[] cserial;
						return true;

					}*/

				}
			}
#endif
		}
	}

	return NULL;

}

XSECKeyInfoResolver * MerlinFiveInteropResolver::clone(void) const {

	return new MerlinFiveInteropResolver(mp_baseURI);

}

<commit_msg>Fix bug with *NIX compile<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "<WebSig>" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Institute for
 * Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>.
 * The development of this software was partly funded by the European
 * Commission in the <WebSig> project in the ISIS Programme.
 * For more information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * XSEC
 *
 * InteropResolver := Class to resolve key elements into certificates for
 *						merlin-18 interop test
 *
 * $Id$
 *
 */

// XSEC

#include "MerlinFiveInteropResolver.hpp"

#include <xsec/framework/XSECDefs.hpp>
#include <xsec/enc/XSECKeyInfoResolver.hpp>
#include <xsec/dsig/DSIGKeyInfoName.hpp>
#include <xsec/dsig/DSIGKeyInfoX509.hpp>
#include <xsec/utils/XSECDOMUtils.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

XERCES_CPP_NAMESPACE_USE

#include <iostream>

#if !defined (HAVE_OPENSSL) && !defined (HAVE_WINCAPI)
#	error Require OpenSSL or Windows Crypto API for the Merlin Resolver
#endif

#if defined (HAVE_OPENSSL)
#	include <openssl/x509.h>
#	include <openssl/pem.h>
#	include <xsec/enc/OpenSSL/OpenSSLCryptoX509.hpp>
#	include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
#   include <xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.hpp>
#endif

#if defined (HAVE_WINCAPI)
#   include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp>
#endif

// --------------------------------------------------------------------------------
//           Strings and keys
// --------------------------------------------------------------------------------

static XMLCh s_bobName[] = {
	chLatin_b,
	chLatin_o,
	chLatin_b,
	chNull
};

static XMLCh s_jobName[] = {
	chLatin_j,
	chLatin_o,
	chLatin_b,
	chNull
};

static XMLCh s_jebName[] = {
	chLatin_j,
	chLatin_e,
	chLatin_b,
	chNull
};

static XMLCh s_jedName[] = {
	chLatin_j,
	chLatin_e,
	chLatin_d,
	chNull
};

static char s_bobKey[] = "abcdefghijklmnopqrstuvwx";
static char s_jobKey[] = "abcdefghijklmnop";
static char s_jebKey[] = "abcdefghijklmnopqrstuvwx";
static char s_jedKey[] = "abcdefghijklmnopqrstuvwxyz012345";

// --------------------------------------------------------------------------------
//           Construct/Destruct
// --------------------------------------------------------------------------------

MerlinFiveInteropResolver::MerlinFiveInteropResolver(const XMLCh * baseURI) {

	if (baseURI != NULL)
		mp_baseURI = XMLString::replicate(baseURI);
	else
		mp_baseURI = NULL;

#if !defined(_WIN32)
	m_fcount = 0;
#endif

}

MerlinFiveInteropResolver::~MerlinFiveInteropResolver() {

	if (mp_baseURI != NULL)
		delete[]mp_baseURI;

}
// --------------------------------------------------------------------------------
//			Utility functions
// --------------------------------------------------------------------------------
#if defined(_WIN32)

void reverseSlash(safeBuffer &path) {

	for (int i = 0; i < strlen(path.rawCharBuffer()); ++i) {

		if (path[i] == '/')
			path[i] = '\\';

	}

}

#endif

XSECCryptoSymmetricKey * MerlinFiveInteropResolver::makeSymmetricKey(XSECCryptoSymmetricKey::SymmetricKeyType type) {

#if defined (HAVE_OPENSSL)

	OpenSSLCryptoSymmetricKey * k;
	k = new OpenSSLCryptoSymmetricKey(type);

	return k;

#else

	WinCAPICryptoSymmetricKey * k;
	k = new WinCAPICryptoSymmetricKey(0, type);

	return k;

#endif

}

BIO * createFileBIO(const XMLCh * baseURI, const char * name) {

	// Open file URI relative to the encrypted file

	BIO * bioFile;
	if ((bioFile = BIO_new(BIO_s_file())) == NULL) {

		return NULL;

	}

	safeBuffer fname;
	fname.sbTranscodeIn(baseURI);
	fname.sbStrcatIn("/");
	fname.sbStrcatIn(name);

#if defined(_WIN32)
	reverseSlash(fname);
#endif

	if (BIO_read_filename(bioFile, fname.rawCharBuffer()) <= 0) {

		return NULL;

	}

	return bioFile;
}

// --------------------------------------------------------------------------------
//           Resolver
// --------------------------------------------------------------------------------

XSECCryptoKey * MerlinFiveInteropResolver::resolveKey(DSIGKeyInfoList * lst) {

	int lstSize = lst->getSize();

	for (int i = 0; i < lstSize; ++i) {

		DSIGKeyInfo * ki = lst->item(i);

		if (ki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_NAME) {

			DSIGKeyInfoName * kn = dynamic_cast<DSIGKeyInfoName *>(ki);

			const XMLCh * name = kn->getKeyName();

			// Check if this is a key we know

			if (strEquals(s_bobName, name)) {
				XSECCryptoSymmetricKey * k =
					XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_CBC_192);
				try {
					k->setKey((unsigned char *) s_bobKey, strlen(s_bobKey));
				} catch (...) {
					delete k;
					throw;
				}
				return k;
			}
			if (strEquals(s_jobName, name)) {
				XSECCryptoSymmetricKey * k =
					XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_ECB_128);
				try {
					k->setKey((unsigned char *) s_jobKey, strlen(s_jobKey));
				} catch(...) {
					delete k;
					throw;
				}
				return k;
			}
			if (strEquals(s_jebName, name)) {
				XSECCryptoSymmetricKey * k =
					XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_ECB_192);
				try {
					k->setKey((unsigned char *) s_jebKey, strlen(s_jebKey));
				} catch(...) {
					delete k;
					throw;
				}
				return k;
			}
			if (strEquals(s_jedName, name)) {
				XSECCryptoSymmetricKey * k =
					XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_AES_ECB_256);
				try {
					k->setKey((unsigned char *) s_jedKey, strlen(s_jedKey));
				} catch(...) {
					delete k;
					throw;
				}
				return k;
			}

		}

		else if (ki->getKeyInfoType() == DSIGKeyInfo::KEYINFO_X509) {

			DSIGKeyInfoX509 * kix = dynamic_cast<DSIGKeyInfoX509 *> (ki);

			XSECCryptoX509 * XCX509 = kix->getCertificateCryptoItem(0);

			if (XCX509 != 0) {
#if defined (HAVE_OPENSSL)

				if (strEquals(XCX509->getProviderName(),DSIGConstants::s_unicodeStrPROVOpenSSL)) {

					OpenSSLCryptoX509 * OSSLX509 = dynamic_cast<OpenSSLCryptoX509 *>(XCX509);
					X509 * x509 = OSSLX509->getOpenSSLX509();

					// Check the serial number
					BIGNUM * bnserial = ASN1_INTEGER_to_BN(x509->cert_info->serialNumber, NULL);
					char * xserial = BN_bn2dec(bnserial);
					BN_free(bnserial);

					BIO * rsaFile = createFileBIO(mp_baseURI, "rsa.p8");
					if (rsaFile == NULL)
						return NULL;

					PKCS8_PRIV_KEY_INFO * p8inf;
					p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(rsaFile, NULL);

					EVP_PKEY * pk = EVP_PKCS82PKEY(p8inf);
					OpenSSLCryptoKeyRSA * k = new OpenSSLCryptoKeyRSA(pk);
					return k;
						//d2i_PKCS8PrivateKey_bio(rsaFile, NULL, NULL, NULL);

/*					if (strcmp(xserial, cserial) == 0) {

						OPENSSL_free(xserial);
						delete[] cserial;
						return true;

					}*/

				}
			}
#endif
		}
	}

	return NULL;

}

XSECKeyInfoResolver * MerlinFiveInteropResolver::clone(void) const {

	return new MerlinFiveInteropResolver(mp_baseURI);

}

<|endoftext|>