text:
// __BEGIN_LICENSE__
//  Copyright (c) 2006-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NASA Vision Workbench is licensed under the Apache License,
//  Version 2.0 (the "License"); you may not use this file except in
//  compliance with the License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

/// \file ControlNetwork.cc
///

#include <vw/BundleAdjustment/ControlNetwork.h>
#include <vw/Core/Log.h>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>

// Time Headers
#include <boost/thread/xtime.hpp>
#include <ctime>

#ifdef VW_HAVE_UNISTD_H
#include <unistd.h>
#endif

 ///////////////////////////////////
// Global only to Control Network //
///////////////////////////////////

inline std::string current_posix_time_string() {
  char time_string[2048];
  time_t t = time(0);
  struct tm* time_struct = localtime(&t);
  strftime(time_string, 2048, "%F %T", time_struct);
  return std::string(time_string);
}

inline std::string isis_style_time_string() {
  std::string time = current_posix_time_string();
  boost::erase_all( time, "\n" );
  boost::trim( time );
  boost::replace_all( time, " ", "T" );
  return time;
}

namespace vw {
namespace ba {

  ////////////////////////////
  // Control Measure        //
  ////////////////////////////

  /// Constructor
  ControlMeasure::ControlMeasure( float col, float row,
                                  float col_sigma, float row_sigma,
                                  uint64 image_id,
                                  ControlMeasureType type ) :
    m_col(col), m_row(row), m_col_sigma(col_sigma), m_row_sigma(row_sigma), m_image_id(image_id), m_type(type) {

    // Recording time
    m_date_time = isis_style_time_string();

    m_serialNumber    = "Null";
    m_description     = "Null";
    m_chooserName     = "Null";
    m_ignore          = false;
    m_pixels_dominant = true;

    m_ephemeris_time = m_focalplane_x = m_focalplane_y = m_diameter = 0;
  }

  ControlMeasure::ControlMeasure( ControlMeasureType type ) :
    m_col(0), m_row(0), m_col_sigma(0), m_row_sigma(0), m_image_id(0), m_type(type) {

    // Recording time
    m_date_time = isis_style_time_string();

    m_serialNumber    = "Null";
    m_description     = "Null";
    m_chooserName     = "Null";
    m_ignore          = false;
    m_pixels_dominant = true;

    m_ephemeris_time = m_focalplane_x = m_focalplane_y = m_diameter = 0;
  }

  std::string ControlMeasure::get_image_name(ControlNetwork const& net) const {
    if (net.get_image_list().size() <= m_image_id)
      return "";
    return net.get_image_list()[m_image_id];
  }

  /// Write a compressed binary style of measure
  void ControlMeasure::write_binary( std::ostream &f ) const {
    // Writing out all the strings first
    f << m_serialNumber << char(0) << m_date_time << char(0)
      << m_description << char(0) << m_chooserName << char(0);
    // Writing the binary data
    f.write((char*)&(m_col),             sizeof(m_col));
    f.write((char*)&(m_row),             sizeof(m_row));
    f.write((char*)&(m_col_sigma),       sizeof(m_col_sigma));
    f.write((char*)&(m_row_sigma),       sizeof(m_row_sigma));
    f.write((char*)&(m_diameter),        sizeof(m_diameter));
    f.write((char*)&(m_focalplane_x),    sizeof(m_focalplane_x));
    f.write((char*)&(m_focalplane_y),    sizeof(m_focalplane_y));
    f.write((char*)&(m_ephemeris_time),  sizeof(m_ephemeris_time));
    f.write((char*)&(m_image_id),        sizeof(m_image_id));
    f.write((char*)&(m_ignore),          sizeof(m_ignore));
    f.write((char*)&(m_pixels_dominant), sizeof(m_pixels_dominant));
    f.write((char*)&(m_type),            sizeof(m_type));
  }

  /// Reading a compressed binary style of measure
  void ControlMeasure::read_binary( std::istream &f ) {
    // Reading in all the strings
    std::getline( f, m_serialNumber, '\0' );
    std::getline( f, m_date_time, '\0' );
    std::getline( f, m_description, '\0' );
    std::getline( f, m_chooserName, '\0' );
    // Reading the binary data
    f.read((char*)&(m_col),             sizeof(m_col));
    f.read((char*)&(m_row),             sizeof(m_row));
    f.read((char*)&(m_col_sigma),       sizeof(m_col_sigma));
    f.read((char*)&(m_row_sigma),       sizeof(m_row_sigma));
    f.read((char*)&(m_diameter),        sizeof(m_diameter));
    f.read((char*)&(m_focalplane_x),    sizeof(m_focalplane_x));
    f.read((char*)&(m_focalplane_y),    sizeof(m_focalplane_y));
    f.read((char*)&(m_ephemeris_time),  sizeof(m_ephemeris_time));
    f.read((char*)&(m_image_id),        sizeof(m_image_id));
    f.read((char*)&(m_ignore),          sizeof(m_ignore));
    f.read((char*)&(m_pixels_dominant), sizeof(m_pixels_dominant));
    f.read((char*)&(m_type),            sizeof(m_type));
  }

  /// Write an isis style measure
  void ControlMeasure::write_isis( std::ostream &f ) const {
    f << "    Group = ControlMeasure\n";
    f << "      SerialNumber   = " << m_serialNumber << std::endl;
    f << "      MeasureType    = ";
    if ( m_type == ControlMeasure::Unmeasured ) {
      f << "Unmeasured\n";
    } else if ( m_type == ControlMeasure::Manual ) {
      f << "Manual\n";
    } else if ( m_type == ControlMeasure::Estimated ) {
      f << "Estimated\n";
    } else if ( m_type == ControlMeasure::Automatic ) {
      f << "Automatic\n";
    } else if ( m_type == ControlMeasure::ValidatedManual ) {
      f << "ValidatedManual\n";
    } else if ( m_type == ControlMeasure::ValidatedAutomatic ) {
      f << "ValidatedAutomatic\n";
    } else {
      vw_throw( vw::NoImplErr() << "Invalid Control Measure type." );
    }
    if ( m_type == ControlMeasure::Unmeasured ) {
      // Why do you even exist?
      f << "      Sample         = Null\n";
      f << "      Line           = Null\n";
    } else {
      f << "      Sample         = " << m_col << "\n";
      f << "      Line           = " << m_row << "\n";
      f << "      ErrorLine      = " << m_col_sigma << "\n";
      f << "      ErrorSample    = " << m_row_sigma << "\n";
      f << "      ErrorMagnitude = " << sigma_magnitude() << "\n";
      f << "      FocalPlaneX    = " << m_focalplane_x << "\n";
      f << "      FocalPlaneY    = " << m_focalplane_y << "\n";
    }
    if ( m_ephemeris_time != 0 )
      f << "      EphemerisTime  = " << m_ephemeris_time << "\n";
    if ( m_diameter > 0 )
      f << "      Diameter       = " << m_diameter << "\n";
    if ( !m_date_time.empty() )
      f << "      DateTime       = " << m_date_time << "\n";
    if ( !m_chooserName.empty() )
      f << "      ChooserName    = " << m_chooserName << "\n";
    if ( m_ignore )
      f << "      Ignore         = True\n";
    f << "      Reference      = False\n";    // What is reference?
    if ( m_pixels_dominant )
      f << "      PixelsDominant = True\n";
    else
      f << "      PixelsDominant = False\n";
    f << "    End_Group\n";
  }

  void ControlMeasure::read_isis( std::istream &f ) {

    std::vector<std::string> tokens;
    std::ostringstream ostr;
    std::istringstream converter;
    std::string str;

    // Setting defaults
    m_diameter = 0;
    m_date_time = "";
    m_chooserName = "";
    m_ignore = false;
    m_pixels_dominant = true;

    while (1) {
      if ( f.eof() )
        vw_throw( vw::IOErr() << "Error reading Control Measure, unexpectly hit end of file" );

      // Reading file
      str = "";
      std::getline( f, str );
      boost::split( tokens, str, boost::is_any_of(" =\n") );

      // Cleaning out any tokens that are just ""
      for(std::vector<std::string>::iterator iter = tokens.begin();
          iter != tokens.end(); ++iter ) {
        if ( (*iter).empty() ) {
          iter = tokens.erase(iter);
          iter--;
        }
      }

      // Processing statement
      if ( tokens.empty() )
        continue;

      if ( tokens[0] == "End_Group" )     // End of Control Group
        break;
      else if ( tokens[0] == "SerialNumber" ) {
        read_pvl_property( ostr, tokens );
        m_serialNumber = ostr.str();
      } else if ( tokens[0] == "MeasureType" ) {
        read_pvl_property( ostr, tokens );
        if ( ostr.str() == "Unmeasured" )
          m_type = ControlMeasure::Unmeasured;
        else if ( ostr.str() == "Manual" )
          m_type = ControlMeasure::Manual;
        else if ( ostr.str() == "Estimated" )
          m_type = ControlMeasure::Estimated;
        else if ( ostr.str() == "Automatic" )
          m_type = ControlMeasure::Automatic;
        else if ( ostr.str() == "ValidatedManual" )
          m_type = ControlMeasure::ValidatedManual;
        else if ( ostr.str() == "ValidatedAutomatic" )
          m_type = ControlMeasure::ValidatedAutomatic;
        else
          vw_throw( vw::IOErr() << "Invalid Control Measure type, \""
                    << ostr.str() << "." );
      } else if ( tokens[0] == "Sample" ) {
        read_pvl_property( ostr, tokens );
        if ( ostr.str() == "Null" )
          m_col = 0;
        else {
          converter.str( ostr.str() );
          converter.clear();
          converter >> m_col;
        }
      } else if ( tokens[0] == "Line" ) {
        read_pvl_property( ostr, tokens );
        if ( ostr.str() == "Null" )
          m_row = 0;
        else {
          converter.str( ostr.str() );
          converter.clear();
          converter >> m_row;
        }
      } else if ( tokens[0] == "ErrorLine" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_col_sigma;
      } else if ( tokens[0] == "ErrorSample" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_row_sigma;
      } else if ( tokens[0] == "FocalPlaneX" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_focalplane_x;
      } else if ( tokens[0] == "FocalPlaneY" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_focalplane_y;
      } else if ( tokens[0] == "EphemerisTime" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_ephemeris_time;
      } else if ( tokens[0] == "Diameter" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_diameter;
      } else if ( tokens[0] == "DateTime" ) {
        read_pvl_property( ostr, tokens );
        m_date_time = ostr.str();
      } else if ( tokens[0] == "ChooserName" ) {
        read_pvl_property( ostr, tokens );
        m_chooserName = ostr.str();
      } else if ( tokens[0] == "Ignore" ) {
        m_ignore = true;
      } else if ( tokens[0] == "PixelsDominant" ) {
        boost::to_lower(tokens[1]);
        if ( tokens[1] == "false" )
          m_pixels_dominant = 0;
        else
          m_pixels_dominant = 1;
      }
      if ( m_col_sigma == 0 )
        m_col_sigma = 1;
      if ( m_row_sigma == 0 )
        m_row_sigma = 1;
    }
  }

  /// Write to a CSV stream
  void ControlMeasure::write_csv( std::ostream &f ) const {
    // TODO: Handle spaces and other formatting in the data!
    // Just write everything out to a single comma delimited line.

    const std::string delim = ", ";
    f << m_serialNumber   << delim << m_date_time       << delim
      << m_description    << delim
      << m_chooserName    << delim
      << m_col            << delim << m_row             << delim
      << m_col_sigma      << delim << m_row_sigma       << delim
      << m_diameter       << delim
      << m_focalplane_x   << delim << m_focalplane_y    << delim
      << m_ephemeris_time << delim << m_image_id        << delim
      << (int)m_ignore    << delim << (int)m_pixels_dominant << delim
      << (int)m_type;
  }

  /// Read from a CSV stream
  void ControlMeasure::read_csv( std::istream &f ) {
    // TODO: Handle more formatting possibilities.
    // Grab all of the elements from the input stream.
    std::string str;
    std::getline( f, str ); // Read in one line.

    const std::string delim = ",";
    std::vector<std::string> parts;
    boost::split(parts, str, boost::is_any_of(delim));
    const size_t EXPECTED_SIZE = 16;
    if (parts.size() != EXPECTED_SIZE)
      vw_throw( vw::IOErr() << "Error reading Control Measure, on line: " << str );

    m_serialNumber    = parts[0];
    m_date_time       = parts[1];
    m_description     = parts[2];
    m_chooserName     = parts[3];
    m_col             = atof(parts[ 4].c_str());
    m_row             = atof(parts[ 5].c_str());
    m_col_sigma       = atof(parts[ 6].c_str());
    m_row_sigma       = atof(parts[ 7].c_str());
    m_diameter        = atof(parts[ 8].c_str());
    m_focalplane_x    = atof(parts[ 9].c_str());
    m_focalplane_y    = atof(parts[10].c_str());
    m_ephemeris_time  = atof(parts[11].c_str());
    m_image_id        = atoi(parts[12].c_str());
    m_ignore          = atoi(parts[13].c_str());
    m_pixels_dominant = atoi(parts[14].c_str());
    m_type            = static_cast<ControlMeasureType>(atoi(parts[15].c_str()));
  }

  ////////////////////////////
  // Control Point          //
  ////////////////////////////

  /// Constructor
  ControlPoint::ControlPoint(ControlPointType type) : m_type(type) {
    m_ignore = false;
    m_id = "Null";
  }

  /// Add a measure
  void ControlPoint::add_measure(ControlMeasure const& measure) {
    m_measures.push_back(measure);
  }

  /// Add multiple measures
  void ControlPoint::add_measures(std::vector<ControlMeasure> const& measures) {
    m_measures.insert(m_measures.end(), measures.begin(), measures.end());
  }

  /// Remove the control point at the specified index.
  void ControlPoint::delete_measure(size_t index) {
    if (index >= this->size())
      vw_throw(LogicErr() << "ControlPoint::delete_control_point -- index " << index << " exceeds control point dimensions.");

    iterator iter = this->begin();
    iter += index;

    m_measures.erase(iter);
  }

  /// Find Control Measure
  size_t ControlPoint::find(ControlMeasure const& query) {
    for (size_t i = 0; i < m_measures.size(); ++i)
      if (m_measures[i] == query)
        return i;
    // If no matches are found, return m_measures.size() (the last index + 1)
    return m_measures.size();
  }

  /// Write a compressed binary style of point
  void ControlPoint::write_binary( std::ostream &f ) const {
    // Writing out the string first
    f << m_id << char(0);
    // Writing the binary data
    f.write((char*)&(m_ignore),      sizeof(m_ignore));
    f.write((char*)&(m_position[0]), sizeof(m_position[0]));
    f.write((char*)&(m_position[1]), sizeof(m_position[1]));
    f.write((char*)&(m_position[2]), sizeof(m_position[2]));
    f.write((char*)&(m_sigma[0]),    sizeof(m_sigma[0]));
    f.write((char*)&(m_sigma[1]),    sizeof(m_sigma[1]));
    f.write((char*)&(m_sigma[2]),    sizeof(m_sigma[2]));
    f.write((char*)&(m_type),        sizeof(m_type));
    int size = m_measures.size();
    f.write((char*)&(size),          sizeof(size));
    // Rolling through the measures
    BOOST_FOREACH( ControlMeasure const& cm, m_measures )
      cm.write_binary( f );
  }

  /// Reading a compressed binary style of point
  void ControlPoint::read_binary( std::istream &f ) {
    // Reading in the string first
    std::getline( f, m_id, '\0' );
    // Reading in the binary data
    f.read((char*)&(m_ignore),      sizeof (m_ignore));
    f.read((char*)&(m_position[0]), sizeof (m_position[0]));
    f.read((char*)&(m_position[1]), sizeof (m_position[1]));
    f.read((char*)&(m_position[2]), sizeof (m_position[2]));
    f.read((char*)&(m_sigma[0]),    sizeof (m_sigma[0]));
    f.read((char*)&(m_sigma[1]),    sizeof (m_sigma[1]));
    f.read((char*)&(m_sigma[2]),    sizeof (m_sigma[2]));
    f.read((char*)&(m_type),        sizeof (m_type));
    int size;
    f.read((char*)&(size),          sizeof (size));
    m_measures.clear();
    m_measures.reserve(size);
    // Reading in all the measures
    for ( int m = 0; m < size; m++ ) {
      m_measures.push_back( ControlMeasure(f, FmtBinary) );
    }
  }

  /// Write an isis style point
  void ControlPoint::write_isis( std::ostream &f ) const {
    f << "  Object = ControlPoint\n";
    f << "    PointType = ";
    if ( m_type == ControlPoint::GroundControlPoint ) {
      f << "Ground\n";
    } else if ( m_type == ControlPoint::TiePoint ) {
      f << "Tie\n";
    } else {
      vw_throw( vw::NoImplErr() << "Invalid Control Point type." );
    }
    f << "    PointId   = " << m_id << "\n";
    f << "    Latitude  = " << m_position[1] << "\n";
    f << "    Longitude = " << m_position[0] << "\n";
    f << "    Radius    = " << m_position[2] << "\n";
    if ( m_ignore )
      f << "    Ignore    = True\n";

    // Rolling through measures
    BOOST_FOREACH( ControlMeasure const& m, m_measures ) {
      f << std::endl;
      m.write_isis( f );
    }
    f << "  End_Object\n";
  }

  /// Read an isis style point
  void ControlPoint::read_isis( std::istream &f ) {

    std::vector<std::string> tokens;
    std::ostringstream ostr;
    std::istringstream converter;
    std::string str;

    // Setting defaults
    m_ignore = false;

    m_measures.clear();

    while (1) {
      if ( f.eof() )
        vw_throw( vw::IOErr() << "Error reading Control Point, unexpectly hit end of file" );

      // Reading file
      str = "";
      std::getline( f, str );
      boost::split( tokens, str, boost::is_any_of(" =\n") );

      // Cleaning out any tokens that are just ""
      for(std::vector<std::string>::iterator iter = tokens.begin();
          iter != tokens.end(); ++iter ) {
        if ( (*iter).empty() ) {
          iter = tokens.erase(iter);
          iter--;
        }
      }

      // Processing statement
      if ( tokens.empty() )
        continue;

      if ( tokens[0] == "End_Object" )     // End of Control Point
        break;
      else if ( tokens[0] == "PointType" ) {
        read_pvl_property( ostr, tokens );
        if ( ostr.str() == "Ground" )
          m_type = ControlPoint::GroundControlPoint;
        else if ( ostr.str() == "Tie" )
          m_type = ControlPoint::TiePoint;
        else
          vw_throw( vw::IOErr() << "Invalid Control Point type, \""
                    << ostr.str() << "." );
      } else if ( tokens[0] == "PointId" ) {
        read_pvl_property( ostr, tokens );
        m_id = ostr.str();
      } else if ( tokens[0] == "Latitude" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_position[1];
      } else if ( tokens[0] == "Longitude" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_position[0];
      } else if ( tokens[0] == "Radius" ) {
        read_pvl_property( ostr, tokens );
        converter.str( ostr.str() );
        converter.clear();
        converter >> m_position[2];
      } else if ( tokens[0] == "Ignore" ) {
        m_ignore = tokens[1] == "True";
      } else if ( tokens[0] == "Group" ) {
        if ( tokens.size() == 1 ) {
          vw_throw( IOErr() << "Failed to read Control Point. Contains incorrect syntax, unlabelled Group" );
        } else if ( tokens[1] == "ControlMeasure" ) {
          m_measures.push_back( ControlMeasure( f, FmtIsisPvl ) );
        } else {
          vw_throw( IOErr() << "Failed to read Control Point. Unkown group \"" << tokens[1] << "\" found." );
        }
      }
    }
  }

  /// Write a CSV style of point
  void ControlPoint::write_csv( std::ostream &f ) const {
    const std::string delimiter = ", ";

    // Writing out the header on one line.
    f << m_id << delimiter << (int)m_ignore << delimiter
      << m_position[0] << delimiter << m_position[1] << delimiter << m_position[2] << delimiter
      << m_sigma[0] << delimiter << m_sigma[1] << delimiter << m_sigma[2] << delimiter
      << (int)m_type << delimiter << m_measures.size() << std::endl;

    // Write each measure on its own line.
    BOOST_FOREACH( ControlMeasure const& cm, m_measures ) {
      cm.write_csv( f );
      f << std::endl;
    }
  }

  /// Reading a CSV style of point
  void ControlPoint::read_csv( std::istream &f ) {

    std::string str;
    std::getline( f, str ); // Read in one line.

    const std::string delim = ",";
    std::vector<std::string> parts;
    boost::split(parts, str, boost::is_any_of(delim));
    const size_t EXPECTED_SIZE = 10;
    if (parts.size() != EXPECTED_SIZE)
      vw_throw( vw::IOErr() << "Error reading Control Point, on line: " << str );

    int size;
    m_id          = atoi(parts[0].c_str());
    m_ignore      = atoi(parts[1].c_str());
    m_position[0] = atof(parts[2].c_str());
    m_position[1] = atof(parts[3].c_str());
    m_position[2] = atof(parts[4].c_str());
    m_sigma[0]    = atof(parts[5].c_str());
    m_sigma[1]    = atof(parts[6].c_str());
    m_sigma[2]    = atof(parts[7].c_str());
    m_type        = static_cast<ControlPointType>(atoi(parts[8].c_str()));
    size          = atoi(parts[9].c_str());

    // Read in each of the control measures
    m_measures.clear();
    m_measures.reserve(size);
    // Reading in all the measures
    for ( int m = 0; m < size; m++ ) {
      m_measures.push_back( ControlMeasure(f, FmtCsv) );
    }
  }

  ////////////////////////////
  // Control Network        //
  ////////////////////////////

  /// Constructor
  ControlNetwork::ControlNetwork(std::string id,
                                 ControlNetworkType type,
                                 std::string target_name,
                                 std::string descrip, std::string user_name ) :
    m_targetName(target_name), m_networkId(id), m_description(descrip), m_userName(user_name), m_type(type) {
    // Recording time
    m_created = isis_style_time_string();
  }

  /// Add a single Control Point
  void ControlNetwork::add_control_point(ControlPoint const& point) {
    // Checking for GCPs (if this network supposedly doesn't contain
    // control networks)
    if ( m_type != ControlNetwork::ImageToGround &&
         point.type() == ControlPoint::GroundControlPoint )
      m_type = ControlNetwork::ImageToGround;

    m_control_points.push_back(point);
  }

  /// Add a vector of Control Points
  void ControlNetwork::add_control_points(std::vector<ControlPoint> const& points) {
    // Checking for GCPs (if this network supposedly doesn't contain
    // control networks)
    if ( m_type != ControlNetwork::ImageToGround ) {
      BOOST_FOREACH( ControlPoint const& cp, points ) {
        if ( cp.type() == ControlPoint::GroundControlPoint ) {
          m_type = ControlNetwork::ImageToGround;
          break;
        }
      }
    }

    m_control_points.insert(m_control_points.end(), points.begin(), points.end());
  }

  // Delete control point
  void ControlNetwork::delete_control_point(size_t index) {
    if (index >= this->size())
      vw_throw(LogicErr() << "ControlNetwork::delete_control_point -- index " << index << " exceeds control network dimensions.");

    iterator iter = this->begin();
    iter += index;

    m_control_points.erase(iter);
  }

  // Find measure
  size_t ControlNetwork::find_measure(ControlMeasure const& query) {
    for (size_t i = 0; i < m_control_points.size(); ++i)
      if (m_control_points[i].find(query) != m_control_points[i].size())
        return i;
    // Otherwise...
    return m_control_points.size();
  }

  /// Write a compressed binary style control network
  void ControlNetwork::write_binary( std::string filename ) const {

    // Recording the modified time
    m_modified = isis_style_time_string();

    // Forcing file extension type
    filename = filename.substr(0,filename.rfind("."));
    filename += ".cnet";

    vw_out() << "Writing: " << filename << std::endl;

    // Opening file
    std::ofstream f( filename.c_str(), std::ofstream::binary );

    // Writing out the strings first
    f << m_targetName << char(0) << m_networkId << char(0)
      << m_created << char(0) << m_modified << char(0)
      << m_description << char(0) << m_userName << char(0);
    // Writing the binary data
    f.write((char*)&(m_type), sizeof(m_type));
    int size = m_control_points.size();
    f.write((char*)&(size), sizeof(size));
    // Rolling through the control points
    BOOST_FOREACH( ControlPoint const& cp, m_control_points )
      cp.write_binary( f );

    f.close();
  }

  /// Reading a compressed binary style control network
  void ControlNetwork::read_binary( std::string const& filename ) {

    // Opening file
    std::ifstream f( filename.c_str() );
    if ( !f.is_open() )
      vw_throw( IOErr() << "Failed to open \"" << filename << "\" as a Control Network." );

    // Reading in the strings first
    std::getline( f, m_targetName, '\0' );
    std::getline( f, m_networkId, '\0' );
    std::getline( f, m_created, '\0' );
    std::getline( f, m_modified, '\0' );
    std::getline( f, m_description, '\0' );
    std::getline( f, m_userName, '\0' );

    // Reading in the binary data
    f.read((char*)&(m_type), sizeof(m_type));
    int size;
    f.read((char*)&(size), sizeof(size));

    // Clearing anything left in this control network
    m_control_points.clear();
    m_control_points.reserve( size );

    // Reading in all the control points
    for ( int p = 0; p < size; p++ )
      m_control_points.push_back( ControlPoint( f, FmtBinary ) );

    f.close();
  }

  /// Write an isis style control network
  void ControlNetwork::write_isis( std::string filename ) {
    // Recording the modified time
    m_modified = isis_style_time_string();

    // Forcing file extension type
    filename = filename.substr(0,filename.rfind("."));
    filename += ".net";

    // Making sure all the control points have unique IDs
    size_t cpcount = 0;
    BOOST_FOREACH( ControlPoint& cp, m_control_points ) {
      if ( cp.id() == "Null" || cp.id().empty() ) {
        std::ostringstream ostr;
        ostr << std::setw(9) << std::setfill('0') << cpcount;
        cp.set_id( ostr.str() );
      }
      cpcount++;
    }

    // Opening file
    std::ofstream f( filename.c_str() );
    f << std::setprecision( 15 );

    f << "Object = ControlNetwork\n";
    f << "  NetworkId    = " << m_networkId << "\n";
    f << "  NetworkType  = ";
    if ( m_type == ControlNetwork::Singleton ) {
      f << "Singleton\n";
    } else if ( m_type == ControlNetwork::ImageToImage ) {
      f << "ImageToImage\n";
    } else if ( m_type == ControlNetwork::ImageToGround ) {
      f << "ImageToGround\n";
    } else {
      vw_throw( vw::NoImplErr() << "Invalid Control Network type." );
    }
    f << "  TargetName   = " << m_targetName << "\n";
    f << "  UserName     = " << m_userName << "\n";
    f << "  Created      = " << m_created << "\n";
    f << "  LastModified = " << m_modified << "\n";
    f << "  Description  = " << m_description << "\n";

    // Rolling through the control points
    BOOST_FOREACH( ControlPoint& cp, m_control_points ) {
      f << std::endl;
      cp.write_isis( f );
    }

    f << "End_Object\nEnd\n";
    f.close();
  }

  /// Read an isis style control network
  void ControlNetwork::read_isis( std::string const& filename ) {

    // Opening file
    std::ifstream f( filename.c_str() );
    if ( !f.is_open() )
      vw_throw( IOErr() << "Failed to open \"" << filename << "\" as a ISIS Control Network." );

    // Clearing anything left in this control network
    m_control_points.clear();

    // Reading file
    std::vector<std::string> tokens;
    std::ostringstream ostr;
    std::string str;
    while ( !f.eof() ) {
      // Reading file
      str = "";
      std::getline( f, str);
      boost::split( tokens, str, boost::is_any_of(" =\n") );

      // Cleaning out any tokens that are just ""
      for(std::vector<std::string>::iterator iter = tokens.begin();
          iter != tokens.end(); ++iter ) {
        if ( (*iter).empty() ) {
          iter = tokens.erase(iter);
          iter--;
        }
      }

      // Processing statement
      if ( tokens.empty() )
        continue;

      if ( tokens[0] == "End" )        // End of file
        break;
      else if ( tokens[0] == "NetworkId" ) {
        read_pvl_property( ostr, tokens );
        m_networkId = ostr.str();
      }
      else if ( tokens[0] == "NetworkType" ) {
        read_pvl_property( ostr, tokens );
        if ( ostr.str() == "Singleton" )
          m_type = ControlNetwork::Singleton;
        else if ( ostr.str() == "ImageToImage" )
          m_type = ControlNetwork::ImageToImage;
        else if ( ostr.str() == "ImageToGround" )
          m_type = ControlNetwork::ImageToGround;
        else
          vw_throw( vw::IOErr() << "Invalid Control Network type, \""
                    << ostr.str() << "." );
      }
      else if ( tokens[0] == "TargetName" ) {
        read_pvl_property( ostr, tokens );
        m_targetName = ostr.str();
      }
      else if ( tokens[0] == "UserName" ) {
        read_pvl_property( ostr, tokens );
        m_userName = ostr.str();
      }
      else if ( tokens[0] == "Created" ) {
        read_pvl_property( ostr, tokens );
        m_created = ostr.str();
      }
      else if ( tokens[0] == "LastModified" ) {
        read_pvl_property( ostr, tokens );
        m_modified = ostr.str();
      }
      else if ( tokens[0] == "Description" ) {
        read_pvl_property( ostr, tokens );
        m_description = ostr.str();
      }
      else if ( tokens[0] == "Object" ) {
        if ( tokens.size() == 1 ) {
          vw_throw( IOErr() << "Failed to open \"" << filename
                    << "\". Contains incorrect syntax, unlabelled Object" );
        } else if ( tokens[1] == "ControlNetwork" ) {
          // Start of file
          continue;
        } else if ( tokens[1] == "ControlPoint" ) {
          m_control_points.push_back( ControlPoint( f, FmtIsisPvl  ) );
        } else if ( tokens[1] == "ControlMeasure" ) {
          vw_throw( IOErr() << "Failed to open \"" << filename
                    << "\". Control Measure found out of order." );
        } else {
          vw_throw( IOErr() << "Failed to open \"" << filename
                    << "\". Unknown Object \"" << tokens[1] << "\" found." );
        }
      }
    }
    f.close();
  }

  /// Write a csv style control network
  void ControlNetwork::write_csv( std::string filename ) const {

    // Recording the modified time
    m_modified = isis_style_time_string();

    // Forcing file extension type
    filename = filename.substr(0,filename.rfind("."));
    filename += ".csv";

    vw_out() << "Writing: " << filename << std::endl;

    // Opening file
    std::ofstream f( filename.c_str() );

    // Writing out the strings first
    const std::string delimiter = ", ";
    f << m_targetName << delimiter << m_networkId << delimiter
      << m_created << delimiter << m_modified << delimiter
      << m_description << delimiter << m_userName << delimiter
      << (int)m_type << delimiter << m_control_points.size() << std::endl;

    // Write each control point
    BOOST_FOREACH( ControlPoint const& cp, m_control_points )
      cp.write_csv( f );

    f.close();
  }

  /// Reading a csv style control network
  void ControlNetwork::read_csv( std::string const& filename ) {

    // Opening file
    std::ifstream f( filename.c_str() );
    if ( !f.is_open() )
      vw_throw( IOErr() << "Failed to open \"" << filename << "\" as a Control Network." );

    std::string str;
    std::getline( f, str ); // Read in one line.

    const std::string delim = ",";
    std::vector<std::string> parts;
    boost::split(parts, str, boost::is_any_of(delim));
    const size_t EXPECTED_SIZE = 8;
    if (parts.size() != EXPECTED_SIZE)
      vw_throw( vw::IOErr() << "Error reading Control Network, on line: " << str );

    int size;
    m_targetName  = parts[0];
    m_networkId   = parts[1];
    m_created     = parts[2];
    m_modified    = parts[3];
    m_description = parts[4];
    m_userName    = parts[5];
    m_type        = static_cast<ControlNetworkType>(atoi(parts[6].c_str()));
    size          = atoi(parts[7].c_str());

    // Clearing anything left in this control network
    m_control_points.clear();
    m_control_points.reserve( size );

    // Reading in all the control points
    for ( int p = 0; p < size; p++ )
      m_control_points.push_back( ControlPoint( f, FmtCsv ) );

    f.close();
  }

void ControlNetwork::write_in_gcp_format(std::string const& filename, cartography::Datum const& d) const{

  const std::string UNSPECIFIED_DATUM = "unspecified_datum";
  if (d.name() == UNSPECIFIED_DATUM)
    vw_throw( ArgumentErr() << "FATAL: No datum was specified. "
                            << "Cannot save control network as csv.\n" );

  std::ofstream ofs(filename.c_str());
  ofs.precision(18);

  int count = 0;
  for ( const_iterator iter = begin(); iter != end(); ++iter ) {

    // If to dump only gcp
    //if ( (*iter).type() != ControlPoint::GroundControlPoint ) continue;

    count++;

    // lon,lat,height
    Vector3 llr = d.cartesian_to_geodetic((*iter).position());

    // convert to lat,lon,height
    std::swap(llr[0], llr[1]);

    Vector3 sigma = (*iter).sigma();
    for (size_t ipt = 0; ipt < sigma.size(); ipt++) {
      if (sigma[ipt] <= 0)
        sigma[ipt] = 1;
    }

    ofs << count     << ' ' << llr  [0] << ' ' << llr  [1] << ' ' << llr[2] << ' ';
    ofs << sigma[0]  << ' ' << sigma[1] << ' ' << sigma[2] << ' ';

    for ( ControlPoint::const_iterator measure = (*iter).begin();
          measure != (*iter).end(); ++measure ) {

      if (measure->image_id() >= m_image_names.size())
        vw_throw( ArgumentErr() << "ControlNetwork::write_in_gcp_format: Measure image ID "
                                << measure->image_id() << " exceeds image count: " << m_image_names.size());

      std::string image_name = m_image_names[measure->image_id()];

      ofs << image_name << ' '
          << measure->position()[0] << ' ' << measure->position()[1] << ' '
          << measure->sigma()[0]    << ' ' << measure->sigma()[1];

      if ( measure+1 != (*iter).end())
        ofs << ' ';
      else
        ofs << std::endl;
    }
  }
  ofs.close();
  return;
}

  ////////////////////////////
  // Generic Ostream        //
  ////////////////////////////

  std::ostream& operator<<( std::ostream& os, ControlMeasure const& measure) {
    os << measure.image_id() << ":" << measure.position();
    return os;
  }

  std::ostream& operator<<( std::ostream& os, ControlPoint const& point) {
    os << "[Control Point: " << point.position() << "] ";
    BOOST_FOREACH( ControlMeasure const& cm, point )
      os << cm << " ";
    os << "\n";
    return os;
  }

  std::ostream& operator<<( std::ostream& os, ControlNetwork const& cnet) {
    os << "Control Network: " << cnet.size() << " points.\n";
    BOOST_FOREACH( ControlPoint const& cp, cnet )
      os << "\t" << cp;
    os << "\n";
    return os;
  }

  // Read a single pvl propert
  void read_pvl_property( std::ostringstream& ostr,
                          std::vector<std::string>& tokens ) {
    ostr.str("");
    for ( size_t i = 1; i < tokens.size(); i++ )
      if ( i > 1 )
        ostr << " " << tokens[i];
      else
        ostr << tokens[i];
  }

}} // namespace vw::camera

max_stars_repo_name: maxerbubba/visionworkbench

max_issues_repo_name: maxerbubba/visionworkbench

max_forks_repo_name: maxerbubba/visionworkbench


text:
#include <boost/test/unit_test.hpp>
#include "../memory.hpp"
#include "../memory.t.hpp"

BOOST_AUTO_TEST_SUITE(memory)
BOOST_AUTO_TEST_CASE(first_write_test) {
	Memory a = Memory();
	a.writeByte(0,0xa);
	BOOST_CHECK_EQUAL(0xa, a.readByte(0).payload);
}

BOOST_AUTO_TEST_CASE(write_random_byte_test) {
	//handle byte writes and reads.
	for(int i =0; i< 10; i++) {
		Memory a = Memory();
		unsigned char num = rand()%UCHAR_MAX;
		unsigned long address = rand()%MAXMEMORY;
		//printf("%p\t%X\n", address, num);
		a.writeByte(address,num);
		//a.write<int>(address, num);
		BOOST_CHECK_EQUAL(num, a.readByte(address).payload);
	}
}

BOOST_AUTO_TEST_CASE(write_random_int_test) {
	//handle int writes and reads.
	Memory a = Memory();
	for(int i =0; i< 10; i++) {
		unsigned int num = rand()%UINT_MAX;
		unsigned long address = rand()%MAXMEMORY;
		//printf("%p\t%X\n", address, num);
		a.write<unsigned int>(address,num);
		//a.write<int>(address, num);
		BOOST_CHECK_EQUAL(num, a.read<unsigned int>(address).payload);
	}
}

BOOST_AUTO_TEST_CASE(verify_bounds_checking) {
	Memory a = Memory();
	a.read<int>(MAXMEMORY).valid;
	BOOST_CHECK_EQUAL(a.read<int>(MAXMEMORY).valid, false);
	BOOST_CHECK_EQUAL(a.read<int>(MAXMEMORY+100).valid, false);
	BOOST_CHECK_EQUAL(a.read<int>(0).valid, true);
	BOOST_CHECK_EQUAL(a.read<int>(MAXMEMORY-sizeof(int)).valid, true);
	BOOST_CHECK_EQUAL(a.read<int>(MAXMEMORY/2).valid, true);
}

BOOST_AUTO_TEST_CASE(verify_byte_op) {
	Memory a = Memory();
	a.writeByte(0, 'a');
	a.writeByte(1, 'b');
	a.writeByte(3, 'd');
	a.writeByte(PAGESIZE-2, 'a');
	a.writeByte(PAGESIZE-1, 'b');
	a.writeByte(PAGESIZE, 'c');
	a.writeByte(PAGESIZE+1, 'd');
	a.writeByte(PAGESIZE+2, 'e');
	BOOST_CHECK_EQUAL(a.readByte(0).payload, 'a');
	BOOST_CHECK_EQUAL(a.readByte(1).payload, 'b');
	BOOST_CHECK_EQUAL(a.readByte(3).payload=='a', false);
}

BOOST_AUTO_TEST_CASE(byte_op_behavior) {
	Memory a = Memory();
	a.write<int>(0, 20);
	BOOST_CHECK_EQUAL(a.readByte(0).payload, 20);
	BOOST_CHECK_EQUAL(a.readByte(1).payload, 0);
	BOOST_CHECK_EQUAL(a.readByte(2).payload, 0);
	BOOST_CHECK_EQUAL(a.readByte(3).payload, 0);
}

BOOST_AUTO_TEST_CASE(byte_op_boundary_behavior) {
	Memory a = Memory();
	a.write<int>(PAGESIZE-(sizeof(int))+1, 20);
	BOOST_CHECK_EQUAL(a.readByte(PAGESIZE-(sizeof(int))+1).payload, 20);
	BOOST_CHECK_EQUAL(a.readByte(PAGESIZE-(sizeof(int))+2).payload, 0);
	BOOST_CHECK_EQUAL(a.readByte(PAGESIZE-(sizeof(int))+3).payload, 0);
	BOOST_CHECK_EQUAL(a.readByte(PAGESIZE-(sizeof(int))+4).payload, 0);
}

BOOST_AUTO_TEST_CASE(verify_op_on_split) {
	Memory a = Memory();
	a.write<int>(PAGESIZE-(sizeof(int))+1, 1234567891);
	BOOST_CHECK_EQUAL(a.read<int>(PAGESIZE-(sizeof(int))+1).valid, true);
	BOOST_CHECK_EQUAL(a.read<int>(PAGESIZE-(sizeof(int))+1).payload, 1234567891);
	a.write<long>((2*PAGESIZE)-(sizeof(int))+1, 1234567891234567);
	BOOST_CHECK_EQUAL(a.read<long>((2*PAGESIZE)-(sizeof(int))+1).payload, 1234567891234567);
	BOOST_CHECK_EQUAL(a.read<long>((2*PAGESIZE)-(sizeof(int))+1).valid, true);
}

BOOST_AUTO_TEST_CASE(write_full_int_test) {
	//fully write the first 3 pages and then the last 3 pages.
	Memory a = Memory();
	for(int i =0; i< 3*PAGESIZE; i+=sizeof(int)) {
		unsigned int num = rand()%UINT_MAX;
		a.write<unsigned int>(i,num);
		BOOST_CHECK_EQUAL(num, a.read<unsigned int>(i).payload);
	}

	for(int i =MAXMEMORY-(3*PAGESIZE); i<MAXMEMORY-sizeof(int); i+=sizeof(int)) {
		unsigned int num = rand()%UINT_MAX;
		a.write<unsigned int>(i,num);
		BOOST_CHECK_EQUAL(num, a.read<unsigned int>(i).payload);
	}
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_stars_repo_name: noah-witt/riscv-engine

max_issues_repo_name: noah-witt/riscv-engine

max_forks_repo_name: noah-witt/riscv-engine


text:
#ifndef _INCLUDE_RSOPEN_SERVICE_HPP_
#define _INCLUDE_RSOPEN_SERVICE_HPP_

// standard/system headers
#include <string>
#include <rtdb_types.h>
#include <boost/thread.hpp>
#include "comm.hpp"
#include "RtDB2Context.h"

namespace rsopen
{

class Service
{
public:
    Service();

    void start();
    void stop();

private:
    std::string m_configfile;
    std::unique_ptr<Comm> m_subscriber;
    std::unique_ptr<Comm> m_publisher;
    std::vector<boost::thread> rtdb_threads;

    void startSubscriber();
    void startPublisher();
    std::string binPath() const;
    std::string configFile() const;
    bool existsFile(const std::string& name) const;
}; // end of class Robot

} // end of namespace mtp

#endif

ext: hpp

max_stars_repo_name: RobBurgers/rsopenapi

max_issues_repo_name: RobBurgers/rsopenapi

max_forks_repo_name: RobBurgers/rsopenapi


text:
/********************************************************************************
 *  File Name:
 *    test_exti_entry.cpp
 *
 *  Description:
 *    Tests the LLD EXTI driver for the STM32L4 port
 *
 *  2020 | Brandon Braun | brandonbraun653@gmail.com
 *******************************************************************************/

/* STL Includes */
#include <array>
#include <cstring>
#include <memory>

/* Boost Includes */
#include <boost/circular_buffer.hpp>

/* Chimera Includes */
#include <Chimera/common>
#include <Chimera/gpio>
#include <Chimera/serial>
#include <Chimera/thread>

/* CppUTest Includes */
#include <CppUTest/CommandLineTestRunner.h>

/*-------------------------------------------------------------------------------
Constants
-------------------------------------------------------------------------------*/
static constexpr Chimera::Serial::Channel serialChannel = Chimera::Serial::Channel::SERIAL1;

/*-------------------------------------------------------------------------------
Static Declarations
-------------------------------------------------------------------------------*/
static void test_thread( void *argument );
static void initializeSerial();

/*-------------------------------------------------------------------------------
Static Data
-------------------------------------------------------------------------------*/
static std::array<char, 100> printBuffer;

/*-------------------------------------------------
Serial Driver Configuration
-------------------------------------------------*/
// Length of the hardware buffer for transceiving a Serial message
static constexpr size_t HWBufferSize = 128;

// Length of the user buffer for queueing multiple messages
static constexpr size_t CircularBufferSize = 2 * HWBufferSize;

// Serial Transmit Buffers
static std::array<uint8_t, HWBufferSize> sTXHWBuffer;
static boost::circular_buffer<uint8_t> sTXCircularBuffer( CircularBufferSize );

// Serial Recieve Buffers
static std::array<uint8_t, HWBufferSize> sRXHWBuffer;
static boost::circular_buffer<uint8_t> sRXCircularBuffer( CircularBufferSize );

/*-------------------------------------------------------------------------------
Public Functions
-------------------------------------------------------------------------------*/
int main()
{
  using namespace Chimera::Threading;
  ChimeraInit();

  Thread testing;
  testing.initialize( test_thread, nullptr, Priority::LEVEL_3, STACK_KILOBYTES( 10 ), "test" );
  testing.start();

  startScheduler();
  return 0;
}

static void initializeSerial()
{
  using namespace Chimera::Serial;
  using namespace Chimera::Hardware;

  /*------------------------------------------------
  Configuration info for the serial object
  ------------------------------------------------*/
  IOPins pins;
  pins.tx.alternate = Chimera::GPIO::Alternate::USART1_TX;
  pins.tx.drive     = Chimera::GPIO::Drive::ALTERNATE_PUSH_PULL;
  pins.tx.pin       = 9;
  pins.tx.port      = Chimera::GPIO::Port::PORTA;
  pins.tx.pull      = Chimera::GPIO::Pull::NO_PULL;
  pins.tx.threaded  = true;
  pins.tx.validity  = true;

  pins.rx.alternate = Chimera::GPIO::Alternate::USART1_RX;
  pins.rx.drive     = Chimera::GPIO::Drive::ALTERNATE_PUSH_PULL;
  pins.rx.pin       = 10;
  pins.rx.port      = Chimera::GPIO::Port::PORTA;
  pins.rx.pull      = Chimera::GPIO::Pull::NO_PULL;
  pins.rx.threaded  = true;
  pins.rx.validity  = true;

  Config cfg;
  cfg.baud     = 115200;
  cfg.flow     = FlowControl::FCTRL_NONE;
  cfg.parity   = Parity::PAR_NONE;
  cfg.stopBits = StopBits::SBITS_ONE;
  cfg.width    = CharWid::CW_8BIT;

  /*------------------------------------------------
  Create the serial object and initialize it
  ------------------------------------------------*/
  auto result = Chimera::Status::OK;
  auto Serial = Chimera::Serial::getDriver( serialChannel );

  if ( !Serial )
  {
    Chimera::insert_debug_breakpoint();
  }

  result |= Serial->assignHW( serialChannel, pins );
  result |= Serial->configure( cfg );
  result |= Serial->enableBuffering( SubPeripheral::TX, &sTXCircularBuffer, sTXHWBuffer.data(), sTXHWBuffer.size() );
  result |= Serial->enableBuffering( SubPeripheral::RX, &sRXCircularBuffer, sRXHWBuffer.data(), sRXHWBuffer.size() );
  result |= Serial->begin( PeripheralMode::INTERRUPT, PeripheralMode::INTERRUPT );
}

static void test_thread( void *argument )
{
  /*-------------------------------------------------
  Configure the output style:
    - Colorized
    - Verbose
  -------------------------------------------------*/
  const char *av_override[] = { "-c", "-v" };

  /*-------------------------------------------------
  Initialize HW Resources
  -------------------------------------------------*/
  initializeSerial();

  /*-------------------------------------------------
  Allocate the device drivers
  -------------------------------------------------*/
  auto serial = Chimera::Serial::getDriver( serialChannel );

  /*-------------------------------------------------
  Run the tests then break
  -------------------------------------------------*/
  snprintf( printBuffer.data(), printBuffer.size(), "\rStarting STM32L4 LLD EXTI Tests\r\n" );
  serial->lock();
  serial->write( printBuffer.data(), strlen( printBuffer.data() ) );
  serial->await( Chimera::Event::Trigger::TRIGGER_WRITE_COMPLETE, Chimera::Threading::TIMEOUT_BLOCK );
  serial->unlock();

  int rcode = CommandLineTestRunner::RunAllTests( 2, av_override );

  snprintf( printBuffer.data(), printBuffer.size(), "Test exit with code: %d\r\n", rcode );
  serial->lock();
  serial->write( printBuffer.data(), strlen( printBuffer.data() ) );
  serial->await( Chimera::Event::Trigger::TRIGGER_WRITE_COMPLETE, Chimera::Threading::TIMEOUT_BLOCK );
  serial->unlock();

  while ( 1 )
  {
    Chimera::insert_debug_breakpoint();
  }
}


text: #include <boost/units/base_units/astronomical/light_minute.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text: #include <boost/accumulators/numeric/functional/vector.hpp>


text:
#include <boost/certify/detail/status_cache.hpp>
#include <boost/certify/detail/spki_blacklist.hpp>
#include <boost/core/lightweight_test.hpp>
#include <thread>

int
main()
{
    namespace bc = boost::certify;
    namespace sc = std::chrono;

    {
        // Empty cache returns status unknown
        bc::status_cache cache;
        BOOST_TEST(cache.check("AAA") == bc::certificate_status::unknown);
    }

    {
        bc::status_cache cache;
        BOOST_TEST(cache.check("AAA") == bc::certificate_status::unknown);
        cache.mark_valid("AAA", sc::system_clock::now() + sc::seconds{120});
        BOOST_TEST(cache.check("AAA") == bc::certificate_status::valid);
        cache.revoke("AAA");
        BOOST_TEST(cache.check("AAA") == bc::certificate_status::revoked);

        // If we ever see a revocation, mark_valid must not update
        cache.mark_valid("AAA", sc::system_clock::now() + sc::seconds{120});
        BOOST_TEST(cache.check("AAA") == bc::certificate_status::revoked);
    }

    {
        bc::status_cache cache;
        cache.mark_valid("AAA", sc::system_clock::now() + sc::microseconds{10});
        std::this_thread::sleep_for(std::chrono::microseconds{11});
        BOOST_TEST(cache.check("AAA") == bc::certificate_status::unknown);

        // Stale validity check must not update the status
        cache.mark_valid("AAA", sc::system_clock::now() - sc::microseconds{10});
        BOOST_TEST(cache.check("AAA") == bc::certificate_status::unknown);
    }

    {
        // Use blacklist
        bc::status_cache cache;
        std::string str{bc::detail::spki_blacklist[0].begin(), bc::detail::spki_blacklist[0].end()};
        cache.revoke(str);
        BOOST_TEST(cache.check(str) == bc::certificate_status::revoked);
    }

    return boost::report_errors();
}

max_stars_repo_name: amenshov/certify

max_issues_repo_name: amenshov/certify

max_forks_repo_name: amenshov/certify


text:
#ifndef VIZE_GL_FRAMEBUFFER_TEXTURE_2D_HPP
#define VIZE_GL_FRAMEBUFFER_TEXTURE_2D_HPP

#include "vize/config.hpp"

#include <boost/noncopyable.hpp>

namespace vize {

/**
 * @author O Programador
 */
class GLFramebufferTexture2D final : boost::noncopyable {
public:
	GLFramebufferTexture2D(SizeType textureWidth, SizeType textureHeight);
	~GLFramebufferTexture2D();

public:
	void resizeTexture(SizeType textureWidth, SizeType textureHeight);

	inline GLuint getFramebufferID() const { return _framebufferID; }
	inline GLuint getTextureID() const { return _textureID; }

private:
	GLuint _framebufferID = GLuint(0);
	GLuint _textureID = GLuint(0);
};

}

#endif // VIZE_GL_FRAMEBUFFER_TEXTURE_2D_HPP

max_stars_repo_name: oprogramadorreal/vize

max_issues_repo_name: oprogramadorreal/vize

max_forks_repo_name: oprogramadorreal/vize


text:
#define BOOST_TEST_MODULE VexContext
#include <boost/test/unit_test.hpp>
#include <vexcl/devlist.hpp>
#include <vexcl/vector.hpp>

void local_context() {
#if defined(VEXCL_BACKEND_OPENCL) || defined(VEXCL_BACKEND_COMPUTE)
    vex::Context ctx( vex::Filter::Exclusive( vex::Filter::Env ) );
#else
    vex::Context ctx( vex::Filter::Env );
#endif
    std::cout << ctx << std::endl;

    BOOST_CHECK( !ctx.empty() );

    const size_t n = 1024;

    vex::vector<int> x(ctx, n);
    x = 0;

    BOOST_CHECK(x.size() == n);
    BOOST_CHECK(x[0] == 0);
}

BOOST_AUTO_TEST_CASE(create_destroy)
{
    // This should work on NVIDIA GPUs with exclusive compute mode.
    local_context();
    local_context();
}

max_stars_repo_name: lkusch/Kratos

max_issues_repo_name: lkusch/Kratos

max_forks_repo_name: lkusch/Kratos


text:
#ifdef DOXYGEN_SHOULD_SKIP_THIS
/**
   Copyright (C) 2015 Jennifer Buehler

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

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

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

#include <boost/thread/mutex.hpp>
#include <gazebo_joint_control/JointController.h>
#include <gazebo/physics/Model.hh>

#include <map>
#include <string>

using gazebo::physics::ModelPtr;
using gazebo::physics::JointPtr;
// using gazebo::physics::JointController;
using gazebo::physics::JointControllerThreadsafe;
using gazebo::common::PID;
using gazebo::common::Time;

JointControllerThreadsafe::JointControllerThreadsafe(ModelPtr& _parent, JointControllerThreadsafe::JointControllerImplPtr& _jointController)
    : Base(boost::dynamic_pointer_cast<Base>(_parent)),
      jointController(_jointController)
{
    Base::SetName(UniqueName());
}

JointControllerThreadsafe::~JointControllerThreadsafe()
{
}

void JointControllerThreadsafe::AddJoint(JointPtr _joint)
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    jointController->AddJoint(_joint);
}

void JointControllerThreadsafe::Update()
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    jointController->Update();
}

void JointControllerThreadsafe::Reset()
{
//    std::cout<<"Reset JointController"<<std::endl;
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    jointController->Reset();
}

void JointControllerThreadsafe::SetJointPosition(const std::string &_name, double _position, int _index)
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    jointController->SetJointPosition(_name, _position, _index);
}

void JointControllerThreadsafe::SetJointPositions(const std::map<std::string, double> &_jointPositions)
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    jointController->SetJointPositions(_jointPositions);
}

gazebo::common::Time JointControllerThreadsafe::GetLastUpdateTime() const
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->GetLastUpdateTime();
}

std::map<std::string, JointPtr> JointControllerThreadsafe::GetJoints() const
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->GetJoints();
}

void JointControllerThreadsafe::SetPositionPID(const std::string &_jointName, const common::PID &_pid)
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    jointController->SetPositionPID(_jointName, _pid);
}

bool JointControllerThreadsafe::SetPositionTarget(const std::string &_jointName, double _target)
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->SetPositionTarget(_jointName, _target);
}

void JointControllerThreadsafe::SetVelocityPID(const std::string &_jointName, const common::PID &_pid)
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    jointController->SetVelocityPID(_jointName, _pid);
}

bool JointControllerThreadsafe::SetVelocityTarget(const std::string &_jointName, double _target)
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->SetVelocityTarget(_jointName, _target);
}

std::map<std::string, gazebo::common::PID> JointControllerThreadsafe::GetPositionPIDs() const
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->GetPositionPIDs();
}

std::map<std::string, gazebo::common::PID> JointControllerThreadsafe::GetVelocityPIDs() const
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->GetVelocityPIDs();
}

std::map<std::string, double> JointControllerThreadsafe::GetForces() const
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->GetForces();
}

std::map<std::string, double> JointControllerThreadsafe::GetPositions() const
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->GetPositions();
}

std::map<std::string, double> JointControllerThreadsafe::GetVelocities() const
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    return jointController->GetVelocities();
}

void JointControllerThreadsafe::SetJointPosition(JointPtr _joint, double _position, int _index)
{
    boost::unique_lock<boost::recursive_mutex> l(mtx);
    jointController->SetJointPosition(_joint, _position, _index);
}

max_stars_repo_name: JenniferBuehler/joint-control-pkgs


text:
// Copyright 2020 The Defold Foundation
// Licensed under the Defold License version 1.0 (the "License"); you may not use
// this file except in compliance with the License.
//
// You may obtain a copy of the License, together with FAQs at
// https://www.defold.com/license
//
// 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 "gameobject.h"
#include "component.h"
#include "comp_anim.h"
#include "comp_script.h"
#include <dlib/log.h>

namespace dmGameObject
{
    static Result CompScriptcInit(const ComponentTypeCreateCtx* ctx, ComponentType* type)
    {
        ComponentTypeSetPrio(type, 200);
        ComponentTypeSetContext(type, ctx->m_Script);
        ComponentTypeSetHasUserData(type, true);
        ComponentTypeSetReadsTransforms(type, true);

        ComponentTypeSetNewWorldFn(type, CompScriptNewWorld);
        ComponentTypeSetDeleteWorldFn(type, CompScriptDeleteWorld);
        ComponentTypeSetCreateFn(type, CompScriptCreate);
        ComponentTypeSetDestroyFn(type, CompScriptDestroy);
        ComponentTypeSetInitFn(type, CompScriptInit);
        ComponentTypeSetFinalFn(type, CompScriptFinal);
        ComponentTypeSetAddToUpdateFn(type, CompScriptAddToUpdate);
        ComponentTypeSetUpdateFn(type, CompScriptUpdate);
        ComponentTypeSetOnMessageFn(type, CompScriptOnMessage);
        ComponentTypeSetOnInputFn(type, CompScriptOnInput);
        ComponentTypeSetOnReloadFn(type, CompScriptOnReload);
        ComponentTypeSetSetPropertiesFn(type, CompScriptSetProperties);
        ComponentTypeSetGetPropertyFn(type, CompScriptGetProperty);
        ComponentTypeSetSetPropertyFn(type, CompScriptSetProperty);
        ComponentTypeSetPropertyIteratorFn(type, CompScriptIterProperties);

        return dmGameObject::RESULT_OK;
    }

    static Result CompAnimcInit(const ComponentTypeCreateCtx* ctx, ComponentType* type)
    {
        ComponentTypeSetPrio(type, 250);
        ComponentTypeSetReadsTransforms(type, true);
        ComponentTypeSetNewWorldFn(type, CompAnimNewWorld);
        ComponentTypeSetDeleteWorldFn(type, CompAnimDeleteWorld);
        ComponentTypeSetAddToUpdateFn(type, CompAnimAddToUpdate);
        ComponentTypeSetUpdateFn(type, CompAnimUpdate);
        return dmGameObject::RESULT_OK;
    }

}

DM_DECLARE_COMPONENT_TYPE(ComponentTypeAnim, "animc", dmGameObject::CompAnimcInit);
DM_DECLARE_COMPONENT_TYPE(ComponentTypeScript, "scriptc", dmGameObject::CompScriptcInit);

max_stars_repo_name: hakoptak/defold

max_issues_repo_name: hakoptak/defold

max_forks_repo_name: hakoptak/defold


text:
#ifndef __IRODS_AUTH_FACTORY_HPP__
#define __IRODS_AUTH_FACTORY_HPP__

// =-=-=-=-=-=-=-
#include "irods/irods_stacktrace.hpp"
#include "irods/irods_auth_object.hpp"

// =-=-=-=-=-=-=-
// boost includes
#include <boost/shared_ptr.hpp>

namespace irods {
/// =-=-=-=-=-=-=-
/// @brief super basic free factory function to create an auth object
///        given the requested authentication scheme
    irods::error auth_factory(
        const std::string&,         // auth scheme
        rError_t*,                  // error object for auth ctor
        irods::auth_object_ptr& ); // auth object pointer

}; // namespace irods

#endif // __IRODS_AUTH_FACTORY_HPP__

max_stars_repo_name: aghsmith/irods

max_issues_repo_name: selroc/irods

max_forks_repo_name: selroc/irods


text:
/*
	Copyright 2005-2007 Adobe Systems Incorporated
	Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
	or a copy at http://stlab.adobe.com/licenses.html)
*/

/*************************************************************************************************/

#include <adobe/config.hpp>

#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>

#include <adobe/enum_ops.hpp>

enum Number {
    num_neg_one=-1,
    num_0 = 0,
    num_1 = 1,
    num_2 = 2,
    num_3 = 3,
    num_4 = 4,
    num_5 = 5,
    num_6 = 6,
    num_7 = 7
};

ADOBE_DEFINE_BITSET_OPS(Number)

BOOST_AUTO_TEST_CASE(enum_bitset_ops) {
    Number x;

// or
    x = num_1 | num_2;
    BOOST_CHECK(x == 3);

// and
    x = num_3 & num_1;
    BOOST_CHECK(x == 1);

// xor
    x = num_2 ^ num_3;
    BOOST_CHECK(x == 1);

// not
    x = num_7 & (~ num_5);
    BOOST_CHECK(x == 2);

// or=
    x = num_1;
    x |= num_2;
    BOOST_CHECK(x == 3);

// and=
    x = num_3;
    x &= num_1;
    BOOST_CHECK(x == 1);

// xor
    x = num_2;
    x ^= num_3;
    BOOST_CHECK(x == 1);
}

ADOBE_DEFINE_ARITHMETIC_OPS(Number)
BOOST_AUTO_TEST_CASE(enum_arith_ops) {
    Number x;

// +
    x = num_1 + num_2;
    BOOST_CHECK(x == 3);

// -
    x = num_3 - num_1;
    BOOST_CHECK(x == 2);

// - (unary)
    x = -num_neg_one;
    BOOST_CHECK(x == 1);

// *
    x = num_2 * num_3;
    BOOST_CHECK(x == 6);

// /
    x = num_5 / num_2;
    BOOST_CHECK(x == 2);

// %
    x = num_5 % num_2;
    BOOST_CHECK(x == 1);

// +=
    x = num_1;
    x+= num_2;
    BOOST_CHECK(x == 3);

// -=
    x = num_3;
    x -= num_1;
    BOOST_CHECK(x == 2);

// *=
    x = num_2;
    x *= num_3;
    BOOST_CHECK(x == 6);

// /=
    x = num_5;
    x /= num_2;
    BOOST_CHECK(x == 2);

// %=
    x = num_5;
    x %= num_2;
    BOOST_CHECK(x == 1);
}

max_stars_repo_name: brycelelbach/asl

max_issues_repo_name: brycelelbach/asl

max_forks_repo_name: brycelelbach/asl


text: #include <boost/compute/algorithm/binary_search.hpp>


text:
/*
 [auto_generated]
 boost/numeric/odeint/util/detail/is_range.hpp

 [begin_description]
 is_range implementation. Taken from the boost::range library.
 [end_description]

 Copyright Thorsten Ottosen 2003-2004

 Distributed under the Boost Software License, Version 1.0.
 (See accompanying file LICENSE_1_0.txt or
 copy at http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_NUMERIC_ODEINT_UTIL_DETAIL_IS_RANGE_HPP_INCLUDED
#define BOOST_NUMERIC_ODEINT_UTIL_DETAIL_IS_RANGE_HPP_INCLUDED

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

#include <cstddef>
#include <boost/range/config.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/and.hpp>

namespace boost {
namespace numeric {
namespace odeint {

namespace range_detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator)
    BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator)
}

namespace detail
{

template< typename Range >
struct is_range : boost::mpl::and_<range_detail::has_iterator<Range>, range_detail::has_const_iterator<Range> >
{
};

//////////////////////////////////////////////////////////////////////////
// pair
//////////////////////////////////////////////////////////////////////////

template< typename iteratorT >
struct is_range< std::pair<iteratorT,iteratorT> > : boost::mpl::true_
{
};

template< typename iteratorT >
struct is_range< const std::pair<iteratorT,iteratorT> > : boost::mpl::true_
{
};

//////////////////////////////////////////////////////////////////////////
// array
//////////////////////////////////////////////////////////////////////////

template< typename elementT, std::size_t sz >
struct is_range< elementT[sz] > : boost::mpl::true_
{
};

template< typename elementT, std::size_t sz >
struct is_range< const elementT[sz] > : boost::mpl::true_
{
};

//////////////////////////////////////////////////////////////////////////
// string
//////////////////////////////////////////////////////////////////////////

template<>
struct is_range< char* > : boost::mpl::true_
{
};

template<>
struct is_range< wchar_t* > : boost::mpl::true_
{
};

template<>
struct is_range< const char* > : boost::mpl::true_
{
};

template<>
struct is_range< const wchar_t* > : boost::mpl::true_
{
};

template<>
struct is_range< char* const > : boost::mpl::true_
{
};

template<>
struct is_range< wchar_t* const > : boost::mpl::true_
{
};

template<>
struct is_range< const char* const > : boost::mpl::true_
{
};

template<>
struct is_range< const wchar_t* const > : boost::mpl::true_
{
};

} // namespace detail

} // namespace odeint
} // namespace numeric
} // namespace boost

#endif // BOOST_NUMERIC_ODEINT_UTIL_DETAIL_IS_RANGE_HPP_INCLUDED

max_stars_repo_name: PXLVision/opengv

max_issues_repo_name: PXLVision/opengv

max_forks_repo_name: PXLVision/opengv


text:
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "mock/MockEvent.h"
#include "mock/MockParentEvent.h"
#include <thread>
#include <boost/random.hpp>
#include <gtest/gtest.h>

class TimedEventEnvironment : public ::testing::Environment
{
    public:

        TimedEventEnvironment() : work_(service_) {}

        void SetUp()
        {
            thread_ = new boost::thread(&TimedEventEnvironment::run, this);
        }

        void TearDown()
        {
            service_.stop();
            thread_->join();
            delete thread_;
        }

        void run()
        {
            service_.run();
        }

        boost::asio::io_service service_;

        boost::asio::io_service::work work_;

        boost::thread *thread_;
};

TimedEventEnvironment* const env = dynamic_cast<TimedEventEnvironment*>(testing::AddGlobalTestEnvironment(new TimedEventEnvironment));

/*!
 * @fn TEST(TimedEvent, EventNonAutoDestruc_SuccessEvents)
 * @brief This test checks the correct behavior of launching events.
 * This test launches an event several times.
 * For each one it waits its execution and then launches it again.
 */
TEST(TimedEvent, EventNonAutoDestruc_SuccessEvents)
{
    MockEvent event(env->service_, *env->thread_, 100, false);

    for(int i = 0; i < 10; ++i)
    {
        event.restart_timer();

        ASSERT_TRUE(event.wait(150));
    }

    int successed = event.successed_.load(std::memory_order_relaxed);

    ASSERT_EQ(successed, 10);

    int cancelled = event.cancelled_.load(std::memory_order_relaxed);

    ASSERT_EQ(cancelled, 0);
}

/*!
 * @fn TEST(TimedEvent, EventNonAutoDestruc_CancelEvents)
 * @brief This test  checks the correct behavior of cancelling events.
 * This test launches an event several times and cancels it.
 * For each one it launchs the event and inmediatly it cancels the event.
 * Then it waits until the cancelation is executed.
 */
TEST(TimedEvent, EventNonAutoDestruc_CancelEvents)
{
    MockEvent event(env->service_, *env->thread_, 100, false);

    for(int i = 0; i < 10; ++i)
    {
        event.restart_timer();
        event.cancel_timer();

        ASSERT_TRUE(event.wait(150));
    }

    int successed = event.successed_.load(std::memory_order_relaxed);

    ASSERT_EQ(successed, 0);

    int cancelled = event.cancelled_.load(std::memory_order_relaxed);

    ASSERT_EQ(cancelled, 10);
}

/*!
 * @fn TEST(TimedEvent, EventNonAutoDestruc_RestartEvents)
 * @brief This test checks the correct behaviour of restarting events.
 * This test restart continuisly several events.
 */
TEST(TimedEvent, EventNonAutoDestruc_RestartEvents)
{
    MockEvent event(env->service_, *env->thread_, 100, false);

    for(int i = 0; i < 10; ++i)
    {
        event.cancel_timer();
        event.restart_timer();
    }

    for(int i = 0; i < 10; ++i)
        ASSERT_TRUE(event.wait(150));

    int successed = event.successed_.load(std::memory_order_relaxed);

    ASSERT_EQ(successed, 1);

    int cancelled = event.cancelled_.load(std::memory_order_relaxed);

    ASSERT_EQ(cancelled, 9);
}

/*!
 * @fn TEST(TimedEvent, EventOnSuccessAutoDestruc_SuccessEvents)
 * @brief This test checks the correct behaviour of autodestruction on succesful execution.
 * This test launches an event configured to destroy itself when the event is executed successfully.
 */
TEST(TimedEvent, EventOnSuccessAutoDestruc_SuccessEvents)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 100, false, eprosima::fastrtps::rtps::TimedEvent::ON_SUCCESS);

    event->restart_timer();

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::seconds(1));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventOnSuccessAutoDestruc_CancelEvents)
 * @brief This test checks the event is not destroyed when it is canceled.
 * This test launches an event, configured to destroy itself when the event is executed successfully,
 * several times but inmediatly cancelling it.
 */
TEST(TimedEvent, EventOnSuccessAutoDestruc_CancelEvents)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 100, false, eprosima::fastrtps::rtps::TimedEvent::ON_SUCCESS);

    // Cancel ten times.
    for(int i = 0; i < 10; ++i)
    {
        event->restart_timer();
        event->cancel_timer();

        ASSERT_TRUE(event->wait(150));

        ASSERT_EQ(MockEvent::destructed_, 0);
    }

    int successed = event->successed_.load(std::memory_order_relaxed);

    ASSERT_EQ(successed, 0);

    int cancelled = event->cancelled_.load(std::memory_order_relaxed);

    ASSERT_EQ(cancelled, 10);

    // Last event will be successful.
    event->restart_timer();

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::seconds(1));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventOnSuccessAutoDestruc_QuickCancelEvents)
 * @brief This test checks the event is not destroyed when it is canceled.
 * This test launches an event, configured to destroy itself when the event is executed successfully,
 * several times but inmediatly cancelling it.
 */
TEST(TimedEvent, EventOnSuccessAutoDestruc_QuickCancelEvents)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 1, false, eprosima::fastrtps::rtps::TimedEvent::ON_SUCCESS);

    // Cancel ten times.
    for(int i = 0; i < 10; ++i)
    {
        event->restart_timer();
        event->cancel_timer();

        ASSERT_TRUE(event->wait(100));

        ASSERT_EQ(MockEvent::destructed_, 0);
    }

    int successed = event->successed_.load(std::memory_order_relaxed);

    ASSERT_EQ(successed, 0);

    int cancelled = event->cancelled_.load(std::memory_order_relaxed);

    ASSERT_EQ(cancelled, 10);

    // Last event will be successful.
    event->restart_timer();

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::seconds(1));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventOnSuccessAutoDestruc_RestartEvents)
 * @brief This test checks the event is not destroyed when it is canceled and restarted.
 * This test restarts several events configure to destroy itself when the event is executed successfully.
 *
 */
TEST(TimedEvent, EventOnSuccessAutoDestruc_RestartEvents)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 100, false, eprosima::fastrtps::rtps::TimedEvent::ON_SUCCESS);

    for(int i = 0; i < 10; ++i)
    {
        event->cancel_timer();
        event->restart_timer();
    }

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::seconds(1));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventOnSuccessAutoDestruc_QuickRestartEvents)
 * @brief This test checks the event is not destroyed when it is canceled and restarted.
 * This test restarts several events configure to destroy itself when the event is executed successfully.
 *
 */
TEST(TimedEvent, EventOnSuccessAutoDestruc_QuickRestartEvents)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 1, false, eprosima::fastrtps::rtps::TimedEvent::ON_SUCCESS);

    for(int i = 0; i < 10; ++i)
    {
        event->cancel_timer();
        event->restart_timer();
    }

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::seconds(1));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventAlwaysAutoDestruc_SuccessEvents)
 * @brief This test checks the event is destroyed after a succesful execution.
 * This test launches an event that is configured to destroy itself.
 */
TEST(TimedEvent, EventAlwaysAutoDestruc_SuccessEvents)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 100, false, eprosima::fastrtps::rtps::TimedEvent::ALLWAYS);

    event->restart_timer();

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::seconds(1));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventAlwaysAutoDestruc_CancelEvents)
 * @brief This test check the event is destroy after the cancelation is executed.
 * This test launches an event and imediatly cancels it.
 */
TEST(TimedEvent, EventAlwaysAutoDestruc_CancelEvents)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 100, false, eprosima::fastrtps::rtps::TimedEvent::ALLWAYS);

    event->restart_timer();
    event->cancel_timer();

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::milliseconds(100));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventAlwaysAutoDestruc_CancelEvents)
 * @brief This test checks the event is destroy after the cancelation is executed.
 * This test launches an event and imediatly cancels it.
 */
TEST(TimedEvent, EventAlwaysAutoDestruc_QuickCancelEvents)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 1, false, eprosima::fastrtps::rtps::TimedEvent::ALLWAYS);

    event->restart_timer();
    event->cancel_timer();

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::milliseconds(100));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventNonAutoDestruct_AutoRestart)
 * @brief This test checks an event is able to restart itself.
 * This test launches an event several times and this event also restarts itself.
 */
TEST(TimedEvent, EventNonAutoDestruct_AutoRestart)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;
    MockEvent *event = new MockEvent(env->service_, *env->thread_, 10 , true);

    for(unsigned int i = 0; i < 100; ++i)
    {
        event->restart_timer();
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    int successed = event->successed_.load(std::memory_order_relaxed);

    ASSERT_GE(successed , 100);

    delete event;

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::milliseconds(100));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, EventNonAutoDestruc_AutoRestartAndDeleteRandomly)
 * This test checks an event, configured to restart itself, can be deleted while
 * it is being scheduled.
 * This test launches an event that restarts itself, and then randomly deletes it.
 */
TEST(TimedEvent, EventNonAutoDestruc_AutoRestartAndDeleteRandomly)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;

    boost::mt19937 rng(static_cast<uint32_t>(std::time(nullptr)));
    boost::uniform_int<> range(10, 100);
    boost::variate_generator<boost::mt19937, boost::uniform_int<>> random(rng, range);

    MockEvent* event = new MockEvent(env->service_, *env->thread_, 2, true);

    event->restart_timer();
    boost::this_thread::sleep_for(boost::chrono::milliseconds(random()));

    delete event;

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::milliseconds(100));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @fn TEST(TimedEvent, ParentEventNonAutoDestruc_InternallyDeleteEventNonAutoDestruct)
 * This test checks an event can delete other event while the later is waiting.
 * This test launches an event that internally will destroy other event.
 */
TEST(TimedEvent, ParentEventNonAutoDestruc_InternallyDeleteEventNonAutoDestruct)
{
    // Restart destriction counter.
    MockEvent::destructed_ = 0;

    MockParentEvent event(env->service_, *env->thread_, 10, 2);

    event.restart_timer();

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::milliseconds(300));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

/*!
 * @brief Auxyliary function to be run in multithread tests.
 * It restarts an event in a loop.
 * @param Event to be restarted.
 * @param num_loop Number of loops.
 * @param sleep_time Sleeping time between each loop.
 */
void restart(MockEvent *event, unsigned int num_loop, unsigned int sleep_time)
{
    for(unsigned int i = 0; i < num_loop; ++i)
    {
        event->restart_timer();

        if(sleep_time > 0)
            boost::this_thread::sleep_for(boost::chrono::milliseconds(sleep_time));
    }
}

/*!
 * @brief Auxyliary function to be run in multithread tests.
 * It cancels an event in a loop.
 * @param Event to be restarted.
 * @param num_loop Number of loops.
 * @param sleep_time Sleeping time between each loop.
 */
void cancel(MockEvent *event, unsigned int num_loop, unsigned int sleep_time)
{
    for(unsigned int i = 0; i < num_loop; ++i)
    {
        event->cancel_timer();

        if(sleep_time > 0)
            boost::this_thread::sleep_for(boost::chrono::milliseconds(sleep_time));
    }
}

/*!
 * @fn TEST(TimedEventMultithread, EventNonAutoDestruc_TwoStartTwoCancel)
 * @brief This function checks multithreading usage of events.
 * This function launches four threads. Two threads restart the event, and the other two
 * cancel it.
 */
TEST(TimedEventMultithread, EventNonAutoDestruc_TwoStartTwoCancel)
{
    boost::thread *thr1 = nullptr, *thr2 = nullptr,
        *thr3 = nullptr, *thr4 = nullptr;

    MockEvent event(env->service_, *env->thread_, 3, false);

    // 2 Thread restarting and two thread cancel.
    // Thread 1 -> Restart 100 times waiting 100ms between each one.
    // Thread 2 -> Cancel 100 times waiting 102ms between each one.
    // Thread 3 -> Restart 80 times waiting 110ms between each one.
    // Thread 4 -> Cancel 80 times waiting 112ms between each one.

    thr1 = new boost::thread(restart, &event, 100, 100);
    thr2 = new boost::thread(cancel, &event, 100, 102);
    thr3 = new boost::thread(restart, &event, 80, 110);
    thr4 = new boost::thread(cancel, &event, 80, 112);

    thr1->join();
    thr2->join();
    thr3->join();
    thr4->join();

    delete thr1;
    delete thr2;
    delete thr3;
    delete thr4;

    // Wait until finish the execution of the event.
    int count = 0;
    while(event.wait(150))
        ++count;

    int successed = event.successed_.load(std::memory_order_relaxed);
    int cancelled = event.cancelled_.load(std::memory_order_relaxed);

    ASSERT_EQ(successed + cancelled, count);
}

/*!
 * @fn TEST(TimedEventMultithread, EventNonAutoDestruc_QuickTwoStartTwoCancel)
 * @brief This function checks multithreading usage of events.
 * This function launches four threads. Two threads restart the event, and the other two
 * cancel it.
 */
TEST(TimedEventMultithread, EventNonAutoDestruc_QuickTwoStartTwoCancel)
{
    boost::thread *thr1 = nullptr, *thr2 = nullptr,
        *thr3 = nullptr, *thr4 = nullptr;

    MockEvent event(env->service_, *env->thread_, 3, false);

    // 2 Thread restarting and two thread cancel.
    // Thread 1 -> Restart 100 times waiting 2ms between each one.
    // Thread 2 -> Cancel 100 times waiting 2ms between each one.
    // Thread 3 -> Restart 80 times waiting 3ms between each one.
    // Thread 4 -> Cancel 80 times waiting 3ms between each one.

    thr1 = new boost::thread(restart, &event, 100, 2);
    thr2 = new boost::thread(cancel, &event, 100, 2);
    thr3 = new boost::thread(restart, &event, 80, 4);
    thr4 = new boost::thread(cancel, &event, 80, 4);

    thr1->join();
    thr2->join();
    thr3->join();
    thr4->join();

    delete thr1;
    delete thr2;
    delete thr3;
    delete thr4;

    // Wait until finish the execution of the event.
    int count = 0;
    while(event.wait(150))
        ++count;

    int successed = event.successed_.load(std::memory_order_relaxed);
    int cancelled = event.cancelled_.load(std::memory_order_relaxed);

    ASSERT_EQ(successed + cancelled, count);
}

/*!
 * @fn TEST(TimedEventMultithread, EventNonAutoDestruc_QuickestTwoStartTwoCancel)
 * @brief This function checks multithreading usage of events.
 * This function launches four threads. Two threads restart the event, and the other two
 * cancel it.
 */
TEST(TimedEventMultithread, EventNonAutoDestruc_QuickestTwoStartTwoCancel)
{
    boost::thread *thr1 = nullptr, *thr2 = nullptr,
        *thr3 = nullptr, *thr4 = nullptr;

    MockEvent event(env->service_, *env->thread_, 2, false);

    // 2 Thread restarting and two thread cancel.
    // Thread 1 -> Restart 100 times waiting 0ms between each one.
    // Thread 2 -> Cancel 100 times waiting 0ms between each one.
    // Thread 3 -> Restart 80 times waiting 0ms between each one.
    // Thread 4 -> Cancel 80 times waiting 0ms between each one.

    thr1 = new boost::thread(restart, &event, 100, 0);
    thr2 = new boost::thread(cancel, &event, 100, 0);
    thr3 = new boost::thread(restart, &event, 80, 0);
    thr4 = new boost::thread(cancel, &event, 80, 0);

    thr1->join();
    thr2->join();
    thr3->join();
    thr4->join();

    delete thr1;
    delete thr2;
    delete thr3;
    delete thr4;

    // Wait until finish the execution of the event.
    int count = 0;
    while(event.wait(150))
        ++count;

    int successed = event.successed_.load(std::memory_order_relaxed);
    int cancelled = event.cancelled_.load(std::memory_order_relaxed);

    ASSERT_EQ(successed + cancelled, count);
}

/*!
 * @fn TEST(TimedEventMultithread, EventNonAutoDestruc_FourAutoRestart)
 * @brief This function checks an event, configured to restart itself, is able to
 * be restarted in several threads.
 * This function launches four threads and each one restart the event.
 */
TEST(TimedEventMultithread, EventNonAutoDestruc_FourAutoRestart)
{
    MockEvent::destructed_ = 0;
    boost::thread *thr1 = nullptr, *thr2 = nullptr,
        *thr3 = nullptr, *thr4 = nullptr;

    MockEvent *event = new MockEvent(env->service_, *env->thread_, 2, true);

    // 2 Thread restarting and two thread cancel.
    // Thread 1 -> AutoRestart 100 times waiting 2ms between each one.
    // Thread 2 -> AutoRestart 100 times waiting 3ms between each one.
    // Thread 3 -> AutoRestart 80 times waiting 4ms between each one.
    // Thread 4 -> AutoRestart 80 times waiting 5ms between each one.

    thr1 = new boost::thread(restart, event, 100, 2);
    thr2 = new boost::thread(restart, event, 100, 3);
    thr3 = new boost::thread(restart, event, 80, 4);
    thr4 = new boost::thread(restart, event, 80, 5);

    thr1->join();
    thr2->join();
    thr3->join();
    thr4->join();

    delete thr1;
    delete thr2;
    delete thr3;
    delete thr4;

    // Wait a prudential time before delete the event.
    boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
    delete event;

    std::unique_lock<std::mutex> lock(MockEvent::destruction_mutex_);

    if(MockEvent::destructed_ != 1)
        MockEvent::destruction_cond_.wait_for(lock, std::chrono::seconds(1));

    ASSERT_EQ(MockEvent::destructed_, 1);
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

max_stars_repo_name: zhangzhimin/Fast-RTPS

max_issues_repo_name: zhangzhimin/Fast-RTPS

max_forks_repo_name: zhangzhimin/Fast-RTPS


text:
////////////////////////////////////////////////////////////////////////////////
///
/// \file guarded_operation.hpp
/// ---------------------------
///
/// Copyright (c) Domagoj Saric 2015 - 2016.
///
/// Use, modification and distribution is subject to
/// the Boost Software License, Version 1.0.
/// (See accompanying file LICENSE_1_0.txt or copy at
/// http://www.boost.org/LICENSE_1_0.txt)
///
/// For more information, see http://www.boost.org
///
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
#ifndef guarded_operation_hpp__B181EBDC_EA6B_451A_90D0_B6E1BE57DCA8
#define guarded_operation_hpp__B181EBDC_EA6B_451A_90D0_B6E1BE57DCA8
#pragma once
//------------------------------------------------------------------------------
#include "boost/mmap/mapped_view/mapped_view.hpp"

#ifdef _WIN32
#include <boost/mmap/detail/win32.hpp>

#include <excpt.h>
#else
#include "boost/assert.hpp"
#include "boost/config.hpp"

#include "boost/err/detail/thread_singleton.hpp"

#include <csetjmp>
//#include <sys/signal.h> // requires Android NDK API 21
#include <signal.h>
#endif // _WIN32
//------------------------------------------------------------------------------
namespace boost
{
//------------------------------------------------------------------------------
namespace mmap
{
//------------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
//
// guarded_operation()
// -------------------
//
////////////////////////////////////////////////////////////////////////////////
///
/// \brief Executes <VAR>operation</VAR> on the <VAR>view</VAR> with platform-
/// specific guards in place that will catch access violation errors/signals/
/// exceptions (which might happen if the OS is unable to actually load a part
/// of the requested memory region/view, e.g. if the view represents a file on a
/// network drive and the network connection breaks).
///
/// \throws Whatever Operation or ErrorHandler throw
///
/// <B>POSIX specific</B>: Any calls made by <VAR>operation</VAR> have to be
/// "async signal safe".
///
////////////////////////////////////////////////////////////////////////////////

#ifndef _WIN32
namespace details
{
    struct bailout_context
    {
        ::jmp_buf    jump_buffer;
        void const * exception_location;
    }; // struct bailout_context

    using local_bailout_context = err::detail::thread_singleton<bailout_context>;

    struct ::sigaction const handler
    (([](){
        struct ::sigaction /*const*/ action =
        {
            // not yet supported by GCC in C++ :/
            //.sa_sigaction = ...
            //.sa_flags     = SA_SIGINFO
            {0}
        };
        action.sa_sigaction =
            []( int const signal_code, siginfo_t * __restrict const p_info, void * /*context*/ )
            {
                // "Use of a mapped region can result in these signals:
                // SIGSEGV, SIGBUS.
                // http://man7.org/linux/man-pages/man2/mmap.2.html
                // http://stackoverflow.com/questions/1715413/longjmp-from-signal-handler
                BOOST_ASSERT( signal_code == SIGSEGV || signal_code == SIGBUS );
                auto & context( local_bailout_context::instance() );
                context.exception_location = p_info->si_addr;
                ::siglongjmp( context.jump_buffer, true );
            };
        action.sa_flags = SA_SIGINFO;
        return action;
    })());

    class scoped_signal_handler
    {
    public:
         scoped_signal_handler( int const signal_type ) noexcept : signal_type_( signal_type ) { BOOST_VERIFY( ::sigaction( signal_type_, &handler         , &original_handler_ ) == 0 ); }
        ~scoped_signal_handler(                       ) noexcept                               { BOOST_VERIFY( ::sigaction( signal_type_, &original_handler_, nullptr           ) == 0 ); }

    private:
        scoped_signal_handler( scoped_signal_handler const & ) = delete;
        int const signal_type_;
        struct ::sigaction original_handler_;
    };
} // namespace details
#endif // !_WIN32

template <typename Element, class Operation, class ErrorHandler>
typename std::result_of<Operation( basic_memory_range<Element> )>::type
guarded_operation
(
    basic_memory_range<Element> const view,
    Operation                   const operation,
    ErrorHandler                const error_handler
)
{
#ifdef _WIN32
    void const * exception_location;
    __try
    {
        return operation( view );
    }
    __except
    (
        ( ::GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR )
            ? ( exception_location = (/*::*/GetExceptionInformation())->ExceptionRecord->ExceptionAddress, EXCEPTION_EXECUTE_HANDLER )
            :                                                                                EXCEPTION_CONTINUE_SEARCH
    )
    {
        return error_handler( exception_location );
    }
#else
    details::scoped_signal_handler const handler0( SIGSEGV );
    details::scoped_signal_handler const handler1( SIGBUS  );
    auto & context( details::local_bailout_context::instance() );
    if ( BOOST_UNLIKELY( ::sigsetjmp( context.jump_buffer, 0 ) ) )
        return error_handler( context.exception_location );
    return operation( view );
#endif // OS
}

//------------------------------------------------------------------------------
} // mmap
//------------------------------------------------------------------------------
} // boost
//------------------------------------------------------------------------------
#endif // guarded_operation_hpp

max_stars_repo_name: microblink/mmap

max_issues_repo_name: microblink/mmap

max_forks_repo_name: microblink/mmap