text:
#include <string>
#include <vector>
#include <thread>

#include <boost/property_tree/ptree.hpp>

#include <prime_server/prime_server.hpp>
#include <prime_server/http_protocol.hpp>

#include "midgard/logging.h"
#include "baldr/graphreader.h"

#include "meili/universal_cost.h"
#include "meili/geojson_reader.h"
#include "meili/geojson_writer.h"
#include "meili/map_matcher_factory.h"
#include "meili/map_matcher.h"
#include "meili/match_result.h"

using namespace prime_server;
using namespace valhalla;
using namespace meili;

namespace {

// Credits: http://werkzeug.pocoo.org/
const std::unordered_map<size_t, std::string> kHttpStatusCodes {
  // 1xx
  {100,"Continue"},
  {101,"Switching Protocols"},
  {102,"Processing"},

  // 2xx
  {200,"OK"},
  {201,"Created"},
  {202,"Accepted"},
  {203,"Non Authoritative Information"},
  {204,"No Content"},
  {205,"Reset Content"},
  {206,"Partial Content"},
  {207,"Multi Status"},
  {226,"IM Used"},  // see RFC 322

  // 3xx
  {300,"Multiple Choices"},
  {301,"Moved Permanently"},
  {302,"Found"},
  {303,"See Other"},
  {304,"Not Modified"},
  {305,"Use Proxy"},
  {307,"Temporary Redirect"},

  // 4xx
  {400,"Bad Request"},
  {401,"Unauthorized"},
  {402,"Payment Required"},  // unuse
  {403,"Forbidden"},
  {404,"Not Found"},
  {405,"Method Not Allowed"},
  {406,"Not Acceptable"},
  {407,"Proxy Authentication Required"},
  {408,"Request Timeout"},
  {409,"Conflict"},
  {410,"Gone"},
  {411,"Length Required"},
  {412,"Precondition Failed"},
  {413,"Request Entity Too Large"},
  {414,"Request URI Too Long"},
  {415,"Unsupported Media Type"},
  {416,"Requested Range Not Satisfiable"},
  {417,"Expectation Failed"},
  {418,"I\'m a teapot"},  // see RFC 232
  {422,"Unprocessable Entity"},
  {423,"Locked"},
  {424,"Failed Dependency"},
  {426,"Upgrade Required"},
  {428,"Precondition Required"},  // see RFC 658
  {429,"Too Many Requests"},
  {431,"Request Header Fields Too Large"},
  {449,"Retry With"},  // proprietary MS extensio

  // 5xx
  {500,"Internal Server Error"},
  {501,"Not Implemented"},
  {502,"Bad Gateway"},
  {503,"Service Unavailable"},
  {504,"Gateway Timeout"},
  {505,"HTTP Version Not Supported"},
  {507,"Insufficient Storage"},
  {510,"Not Extended"},
};

inline std::string http_status_code(unsigned code) {
  auto code_itr = kHttpStatusCodes.find(code);
  return code_itr == kHttpStatusCodes.cend() ? "" : code_itr->second;
}

const headers_t::value_type CORS{"Access-Control-Allow-Origin", "*"};
const headers_t::value_type JSON_MIME{"Content-type", "application/json;charset=utf-8"};
const headers_t::value_type JS_MIME{"Content-type", "application/javascript;charset=utf-8"};

template <typename buffer_t>
void serialize_config(MapMatcher& matcher,
                      rapidjson::Writer<buffer_t>& writer)
{
  // Property tree -> string
  std::stringstream ss;
  boost::property_tree::json_parser::write_json(ss, matcher.config());
  const auto& str = ss.str();

  // String -> JSON document
  rapidjson::Document document;
  document.Parse(str.c_str());

  // JSON document -> writer stream
  document.Accept(writer);
}

std::string serialize_response(MapMatcher& matcher,
                               const std::vector<std::vector<MatchResult>>& result_lists,
                               bool is_collection,
                               bool verbose)
{
  const auto route = matcher.config().get<bool>("route"),
          geometry = matcher.config().get<bool>("geometry");

  using buffer_t = rapidjson::StringBuffer;
  buffer_t sb;
  rapidjson::Writer<buffer_t> writer(sb);

  writer.StartObject();

  writer.String("status");
  writer.Uint(200);

  writer.String("message");
  // Need the reference otherwise the c string will be invalidated?
  // TODO possible to make a c string version of http_status_code?
  const auto& status = http_status_code(200);
  writer.String(status.c_str());

  writer.String("data");
  GeoJSONWriter<buffer_t>* geojson_writer;
  if (route) {
    geojson_writer = new GeoJSONRouteWriter<buffer_t>(verbose);
  } else {
    geojson_writer = new GeoJSONMatchedPointsWriter<buffer_t>(verbose);
  }
  if (geometry) {
    if (is_collection) {
      geojson_writer->WriteGeometryCollection(writer, matcher, result_lists);
    } else {
      geojson_writer->WriteGeometry(writer, matcher, result_lists.front());
    }
  } else {
    if (is_collection) {
      geojson_writer->WriteFeatureCollection(writer, matcher, result_lists);
    } else {
      geojson_writer->WriteFeature(writer, matcher, result_lists.front());
    }
  }
  delete geojson_writer;

  if (verbose) {
    writer.String("config");
    serialize_config(matcher, writer);
  }

  writer.EndObject();

  return sb.GetString();
}

worker_t::result_t jsonify_error(const std::string& message,
                                 http_request_info_t& info,
                                 unsigned status_code = 400)
{
  worker_t::result_t result{false};
  rapidjson::StringBuffer sb;
  rapidjson::Writer<rapidjson::StringBuffer> writer(sb);

  writer.StartObject();

  writer.String("status");
  writer.Uint(status_code);

  writer.String("message");
  writer.String(message.c_str());

  writer.EndObject();

  http_response_t response(status_code, http_status_code(status_code), sb.GetString(), {JSON_MIME, CORS});
  response.from_info(info);
  result.messages.emplace_back(response.to_string());

  return result;
}

worker_t::result_t jsonify_success(const std::string& content,
                                   http_request_info_t& info)
{
  worker_t::result_t result{false};
  http_response_t response(200, http_status_code(200), content, headers_t{CORS, JS_MIME});
  response.from_info(info);
  result.messages.emplace_back(response.to_string());
  return result;
}

template <typename T>
inline std::unordered_set<T>
ptree_array_to_unordered_set(const boost::property_tree::ptree& ptree)
{
  std::unordered_set<T> result;
  for (const auto& item : ptree) {
    result.insert(item.second.get_value<T>());
  }
  return result;
}

//TODO: throw this in the header to make it testable?
class mm_worker_t {
 public:
  mm_worker_t(const boost::property_tree::ptree& config)
      : config_(config),
        matcher_factory_(config_),
        customizable_(ptree_array_to_unordered_set<std::string>(config_.get_child("meili.customizable"))),
        verbose_(config_.get<bool>("meili.verbose")) {}

  boost::property_tree::ptree&
  read_preferences_from_request(const http_request_t& request,
                                boost::property_tree::ptree& preferences)
  {
    if (customizable_.empty()) {
      return preferences;
    }
    const auto& query = request.query;
    for (const auto& pair : query) {
      const auto& name = pair.first;
      const auto& values = pair.second;
      if (customizable_.find(name) != customizable_.end()
          && !values.empty()) {
        // String
        if (name == "mode") {
          if (!values.back().empty()) {
            preferences.put<std::string>("mode", values.back());
          }
        }
        // Boolean
        else if (name == "route" || name == "geometry" || name == "verbose") {
          if (values.back() == "false") {
            preferences.put<bool>(name, false);
          } else {
            preferences.put<bool>(name, true);
          }
        }
        // Float
        else {
          if (!values.back().empty()) {
            try {
              // Possibly throw std::invalid_argument or std::out_of_range
              preferences.put<float>(name, std::stof(values.back()));
            } catch (const std::invalid_argument& ex) {
              throw std::invalid_argument("Invalid argument: unable to parse " + name + " to float");
            } catch (const std::out_of_range& ex) {
              throw std::out_of_range("Invalid argument: " + name + " is out of float range");
            }
          }
        }
      }
    }

    return preferences;
  }

  worker_t::result_t work(const std::list<zmq::message_t>& job, void* request_info, const worker_t::interrupt_function_t&) {
    auto& info = *static_cast<http_request_info_t*>(request_info);
    LOG_INFO("Got Map Matching Request " + std::to_string(info.id));

    http_request_t request;

    // Parse HTTP
    try {
      request = http_request_t::from_string(static_cast<const char*>(job.front().data()), job.front().size());
    } catch (const std::runtime_error& ex) {
      return jsonify_error(ex.what(), info);
    }

    if (request.method == method_t::POST) {
      // Read preferences
      boost::property_tree::ptree preferences;
      try {
        read_preferences_from_request(request, preferences);
      } catch (const std::invalid_argument& ex) {
        return jsonify_error(ex.what(), info);
      } catch (const std::out_of_range& ex) {
        return jsonify_error(ex.what(), info);
      }

      // Create a matcher
      MapMatcher* matcher;
      try {
        matcher = matcher_factory_.Create(preferences);
        // TODO: invalid_argument is ambiguous
      } catch (const std::invalid_argument& ex) {
        return jsonify_error(ex.what(), info);
      }

      // Read sequences
      bool is_collection;
      std::vector<std::vector<Measurement>> sequences;
      try {
        GeoJSONReader geojson_reader(matcher->config().get<float>("gps_accuracy"),
                                     matcher->config().get<float>("search_radius"));
        is_collection = geojson_reader.Read(request.body, sequences);
      } catch (const std::invalid_argument& ex) {
        return jsonify_error(ex.what(), info);
      } catch (const SequenceParseError& ex) {
        return jsonify_error(ex.what(), info);
      }

      // Match
      std::vector<std::vector<MatchResult>> result_lists;
      if (is_collection) {
        for (const auto& sequence: sequences) {
          result_lists.push_back(matcher->OfflineMatch(sequence));
        }
      } else {
        result_lists.push_back(matcher->OfflineMatch(sequences.front()));
      }

      // Serialize results
      bool verbose = preferences.get<bool>("verbose", verbose_);
      const auto& content = serialize_response(*matcher, result_lists, is_collection, verbose);

      delete matcher;

      return jsonify_success(content, info);
    } else {
      // Method not support
      return jsonify_error(http_status_code(405), info, 405);
    }
  }

  void cleanup()
  { matcher_factory_.ClearFullCache(); }

 protected:
  const boost::property_tree::ptree config_;
  MapMatcherFactory matcher_factory_;
  std::unordered_set<std::string> customizable_;
  bool verbose_;
};

}

namespace valhalla {

namespace meili {

void run_service(const boost::property_tree::ptree& config) {
  //gets requests from the http server
  auto upstream_endpoint = config.get<std::string>("meili.service.proxy") + "_out";
  //or returns just location information back to the server
  auto loopback_endpoint = config.get<std::string>("httpd.service.loopback");
  auto interrupt_endpoint = config.get<std::string>("httpd.service.interrupt");

  //listen for requests
  zmq::context_t context;
  mm_worker_t meili_worker(config);
  auto work = std::bind(&mm_worker_t::work, std::ref(meili_worker), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
  auto cleanup = std::bind(&mm_worker_t::cleanup, std::ref(meili_worker));
  prime_server::worker_t worker(context, upstream_endpoint, "ipc:///dev/null", loopback_endpoint, interrupt_endpoint, work, cleanup);
  worker.work();

  //TODO: should we listen for SIGINT and terminate gracefully/exit(0)?
}

}

}

ext: cc

max_stars_repo_name: molind/valhalla

max_issues_repo_name: molind/valhalla

max_forks_repo_name: molind/valhalla


text:
#pragma once

//***************************************************************************
//* Copyright (c) 2015 Saint Petersburg State University
//* Copyright (c) 2011-2014 Saint Petersburg Academic University
//* All Rights Reserved
//* See file LICENSE for details.
//***************************************************************************

#include "assembly_graph/components/graph_component.hpp"
#include <boost/optional.hpp>
#include <map>

using namespace omnigraph;

namespace visualization {

namespace printing_parameter_storage {

template<typename ElementId, typename Value>
class ParameterStorage {
public:
    virtual Value GetValue(ElementId element) const = 0;

    virtual ~ParameterStorage() {
    }
};

template<typename ElementId, typename Value>
class MapParameterStorage : public virtual ParameterStorage<ElementId, Value> {
public:
    typedef std::map<ElementId, Value> Storage;
private:
    template<class It>
    static std::map<ElementId, std::string> ConstructMap(It begin, It end, const std::string &color) {
        std::map<ElementId, std::string> result;
        for (auto it = begin; it != end; ++it) {
            result.insert({*it, color});
        }
        return result;
    }

protected:
    std::map<ElementId, Value> storage_;
private:
    boost::optional<Value> default_value_;
public:
    MapParameterStorage(const std::string &default_value):
            default_value_(default_value) {
    }

    MapParameterStorage(const Storage &storage, Value default_value = Value()):
            storage_(storage), default_value_(std::move(default_value)) {
    }

    template<class It>
    MapParameterStorage(It begin, It end, const Value &value, const std::string &default_value):
            storage_(ConstructMap(begin, end, value)), default_value_(default_value) {
    }

    Value GetValue(ElementId element) const {
        auto it = storage_.find(element);
        if (it == storage_.end()) {
            VERIFY(default_value_);
            return default_value_.get();
        }
        return it->second;
    }
};

template<typename ElementId, typename Value>
class DecoratorParameterStorage : public virtual ParameterStorage<ElementId, Value> {
private:
    ParameterStorage<ElementId, Value> inner_storage_;
public:
    DecoratorParameterStorage(ParameterStorage<ElementId, Value> inner_storage) : inner_storage_(
            inner_storage) {
    }

    Value GetInnerValue(ElementId element) {
        return inner_storage_.GetValue(element);
    }
};

}
}

ext: hpp

max_stars_repo_name: STRIDES-Codes/Exploring-the-Microbiome-

max_issues_repo_name: STRIDES-Codes/Exploring-the-Microbiome-

max_forks_repo_name: STRIDES-Codes/Exploring-the-Microbiome-


text:
#ifndef MSTAR_GRID_POLICY_H
#define MSTAR_GRID_POLICY_H

/**************************************************************************
 * Generates policy for grid maps
 **************************************************************************/

#include <vector>
#include <utility>

#include "mstar_type_defs.hpp"
#include "policy.hpp"
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>

namespace mstar{

  /**
   * Generates a policy for a 4 connected grid
   *
   * The internal coordinates are of the form row * num_rows + col
   * Allows for weighting at the goal for free
   *
   * @param world_map matrix of values describing grid true for obstacle,
   *                  false for clear
   * @param goal (row, column) of goal
   *
   * @return Policy object describing problem
   */
  Policy grid_policy(const std::vector<std::vector<bool>> &world_map,
		     const std::pair<int, int> &goal);

  Policy* grid_policy_ptr(const std::vector<std::vector<bool>> &world_map,
			  const std::pair<int, int> &goal);
}

#endif


text:
#pragma once

#include <vulkan/vulkan.h>
#include "utils.hpp"
#include "image.hpp"
#include <boost/variant.hpp>
#include <optional>

namespace my_vulkan
{
    struct swap_chain_t
    {
        struct acquisition_outcome_t
        {
            std::optional<uint32_t> image_index;
            std::optional<acquisition_failure_t> failure;
        };
        swap_chain_t(
            device_t& _device,
            VkSurfaceKHR surface,
            VkExtent2D actual_extent
        );
        swap_chain_t(const swap_chain_t&) = delete;
        swap_chain_t(swap_chain_t&& other) noexcept;
        swap_chain_t& operator=(const swap_chain_t&) = delete;
        swap_chain_t& operator=(swap_chain_t&& other) noexcept;
        const std::vector<image_t>& images();
        VkFormat format() const;
        VkExtent2D extent() const;
        acquisition_outcome_t acquire_next_image(
            VkSemaphore semaphore,
            std::optional<uint64_t> timeout = std::nullopt
        );
        acquisition_outcome_t acquire_next_image(
            VkFence fence,
            std::optional<uint64_t> timeout = std::nullopt
        );
        acquisition_outcome_t acquire_next_image(
            VkSemaphore semaphore,
            VkFence fence,
            std::optional<uint64_t> timeout = std::nullopt
        );
        VkSwapchainKHR get();
        ~swap_chain_t();
        VkDevice device();
    private:
        void cleanup();
        device_t* _device;
        VkSwapchainKHR _swap_chain;
        std::vector<image_t> _images;
        VkFormat _format;
        VkExtent2D _extent;
    };
}


text:
#ifndef SHEAR__COMPILETIME__MAKE_VECTOR_EXCLUDING_HPP
#define SHEAR__COMPILETIME__MAKE_VECTOR_EXCLUDING_HPP

#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/copy_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/equal_to.hpp>

#include <shear/core.hpp>

namespace shear { namespace compiletime {

class missing;

template<
  typename TExclude,
  BOOST_PP_ENUM_BINARY_PARAMS(
    SHEAR_VECTOR_LIMIT,
    typename T, = compiletime::missing BOOST_PP_INTERCEPT
  )>
class make_vector_excluding {
  private:
    typedef mpl::vector<
        BOOST_PP_ENUM_PARAMS(SHEAR_VECTOR_LIMIT, T)
      > vector_with_junk;
  public:
    // Truncate it to exclude the missing and excluded entries
    typedef typename mpl::copy_if<
        vector_with_junk,
        mpl::not_<mpl::or_<
          boost::is_same<mpl::_1, compiletime::missing>,
          boost::is_same<mpl::_1, TExclude>
        > >
      >::type type;
};

}}

#endif // SHEAR__COMPILETIME__MAKE_VECTOR_EXCLUDING_HPP

max_stars_repo_name: jbytheway/shear

max_issues_repo_name: jbytheway/shear

max_forks_repo_name: jbytheway/shear


text:
#include <Eigen/Dense>
#include <cmath>
#include <fstream>
#include <iomanip>
#include <iostream>

#include "simulator.hpp"
#include "spdlog/spdlog.h"

using namespace SnowSimulator;

Simulator::Simulator(MaterialPoints &materialPoints, Grid *grid,
                     SnowModel &snowModel,
                     std::vector<CollisionObject *> colliders)
    : m_materialPoints(materialPoints), m_grid(grid), m_snowModel(snowModel),
      m_colliders(colliders) {
  m_stepCount = 0;
  logger = spdlog::get("snowsim");
}

/**
 * The simulation proceeds as follows:
 *
 * 1. Rasterize particle data to the grid (rasterizeParticlesToGrid)
 * 2. Compute particle volumes and densities (setParticleVolumesAndDensities)
 *    NOTE: This is done only on the first timestep!
 * 3. Compute grid forces (computeGridForces)
 * 4. Update velocities on grid to v_i' (updateGridVelocities)
 * 5. Grid-based body collisions (detectGridCollisions)
 * 6. Solve linear system for semi-implicit integration (solveLinearSystem)
 * 7. Update deformation gradient (updateDeformationGradient)
 * 8. Update particle velocities (updateParticleVelocities)
 * 9. Particle-based body collisions (detectParticleCollisions)
 * 10. Update particle positions (updateParticlePostions)
 **/
void Simulator::advance(double delta_t) {
  logger->info("[Beginning step {} -> advancing by {}]", stepCount(), delta_t);

  rasterizeParticlesToGrid();

  // On the first timestep, we need to compute particle volumes and densities

  if (m_stepCount == 0) {
    setParticleVolumesAndDensities();
  }

  computeGridForces();
  updateGridVelocities(delta_t);

  detectGridCollisions(delta_t);

  explicitIntegration();
  // solveLinearSystem();

  updateDeformationGradient(delta_t);
  updateParticleVelocities(delta_t);
  detectParticleCollisions(delta_t);
  updateParticlePositions(delta_t);

  m_stepCount++;
}

void Simulator::rasterizeParticlesToGrid() {
  // Reset all node properties

  for (auto &node : m_grid->nodes()) {
    node->m_mass = 0;
    node->m_velocity.setZero();
    node->m_nextVelocity.setZero();
    node->m_velocityStar.setZero();
    node->m_force.setZero();
  }

  // Place all particles in their updated cells

  // TODO(kvchen): Comment this out once we fix this bug

  // for (auto &mp : m_materialPoints.particles()) {
  //   Vector3f idx = (mp->m_position.array() / m_grid->m_spacing).floor();
  //   int i = m_grid->vectorToIdx(idx.cast<int>());
  //
  //   if (i < 0 || i >= m_grid->m_gridCells.size()) {
  //     logger->error("Particle index {} exceeds grid boundaries", i);
  //     std::cout << *mp << std::endl;
  //
  //     logger->error("Other particles in the same cell as invalid particle:");
  //     for (auto &other : mp->cell()->particles()) {
  //       if (other == mp) {
  //         continue;
  //       }
  //       logger->error("Distance to invalid particle: {}",
  //                     (other->position() - mp->position()).norm());
  //       std::cout << *other << std::endl;
  //     }
  //   }
  // }

  for (auto &cell : m_grid->cells()) {
    cell->clear();
  }

  for (auto &mp : m_materialPoints.particles()) {
    int idx = m_grid->getParticleIdx(mp);
    if (idx < 0 || idx >= m_grid->m_gridCells.size()) {
      logger->error("Particle index {} exceeds grid boundaries", idx);
      std::cout << *mp << std::endl;
    }

    m_grid->cells()[idx]->addMaterialPoint(mp);
  }

  for (auto &mp : m_materialPoints.particles()) {
    m_grid->forEachNeighbor(mp, [&mp](GridNode *node) {
      double w = node->basisFunction(mp->position());
      node->m_mass += mp->mass() * w;
      node->m_velocity += mp->velocity() * mp->mass() * w;
    });
  }

  for (auto &node : m_grid->nodes()) {
    if (node->m_mass > 0) {
      node->m_velocity /= node->m_mass;
    }
  }
}

void Simulator::setParticleVolumesAndDensities() {
  logger->info("Setting initial particle volumes and densities");

  for (auto const &mp : m_materialPoints.particles()) {
    mp->m_volume = 0;
    mp->m_density = 0;

    m_grid->forEachNeighbor(mp, [&](GridNode *node) {
      mp->m_density += node->m_mass * node->basisFunction(mp->m_position) /
                       pow(m_grid->m_spacing, 3);
    });

    if (mp->m_density != 0) {
      mp->m_volume = mp->m_mass / mp->m_density;
    }
  }
}

void Simulator::computeGridForces() {
  for (auto &mp : m_materialPoints.particles()) {
    JacobiSVD<Matrix3f> svd(mp->m_defElastic, ComputeFullU | ComputeFullV);

    double Jp = mp->m_defPlastic.determinant();
    double Je = mp->m_defElastic.determinant();

    Matrix3f Re = svd.matrixU() * svd.matrixV().transpose();

    double epsilon =
        exp(fmin(m_snowModel.hardeningCoefficient * (1 - Jp), 1e3));

    // Compute the Cauchy stress
    // mu * 2 * (fe - re)_f

    Matrix3f stress =
        epsilon *
        (2 * m_snowModel.initialMu * (mp->m_defElastic - Re) *
             mp->m_defElastic.transpose() +
         Matrix3f::Identity() * (m_snowModel.initialLambda * (Je - 1) * Je));

    m_grid->forEachNeighbor(mp, [mp, &stress](GridNode *node) {
      node->m_force -=
          mp->m_volume * stress * node->gradBasisFunction(mp->m_position);
    });
  }
}

void Simulator::updateGridVelocities(double delta_t) {
  for (auto &node : m_grid->getAllNodes()) {
    if (node->m_mass > 0) {
      node->m_nextVelocity =
          node->m_velocity + delta_t * node->m_force / node->m_mass;
    }

    // Add gravitational forces

    node->m_nextVelocity += Vector3f(0, -9.8, 0) * delta_t;
  }
}

void Simulator::detectGridCollisions(double delta_t) {
  for (auto &node : m_grid->getAllNodes()) {
    node->m_velocityStar = node->m_nextVelocity;

    for (auto &collider : m_colliders) {
      Vector3f position = node->position();
      if (collider->phi(position) > 0) {
        continue;
      }

      Vector3f normal = collider->normal(position);
      Vector3f relVelocity = node->m_velocityStar - collider->velocity();
      double magnitude = relVelocity.dot(normal);

      if (magnitude >= 0) {
        continue;
      }

      Vector3f tangentialVelocity = relVelocity - magnitude * normal;

      // Only apply dynamic friction if the tangential velocity is large
      // compared to the normal

      double normComponent = collider->friction() * magnitude;
      double tangentNorm = tangentialVelocity.norm();

      if (collider->sticky() || tangentNorm <= -normComponent) {
        relVelocity.setZero();
      } else {
        relVelocity = tangentialVelocity * (1 + normComponent / tangentNorm);
      }

      node->m_velocityStar = relVelocity + collider->velocity();
    }
  }
}

void Simulator::explicitIntegration() {
  for (auto &node : m_grid->getAllNodes()) {
    node->m_nextVelocity = node->m_velocityStar;
    // std::cout << node->m_nextVelocity << std::endl;
  }
}

void Simulator::updateDeformationGradient(double delta_t) {
  for (auto &mp : m_materialPoints.particles()) {
    Matrix3f gradVelocity = Matrix3f::Identity();
    m_grid->forEachNeighbor(mp, [mp, delta_t, &gradVelocity](GridNode *node) {
      gradVelocity += delta_t * node->nextVelocity() *
                      node->gradBasisFunction(mp->m_position).transpose();
    });

    Matrix3f defNext = gradVelocity * mp->m_defElastic * mp->m_defPlastic;
    mp->m_defElastic = gradVelocity * mp->m_defElastic;

    // Push deformations exceeding critical deformation thresholds into Fp

    JacobiSVD<Matrix3f> svd(mp->m_defElastic, ComputeFullU | ComputeFullV);
    Matrix3f sigma = svd.singularValues()
                         .cwiseMax(1 - m_snowModel.criticalCompression)
                         .cwiseMin(1 + m_snowModel.criticalStretch)
                         .asDiagonal();

    mp->m_defPlastic =
        svd.matrixV() * sigma.inverse() * svd.matrixU().transpose() * defNext;
    mp->m_defElastic = svd.matrixU() * sigma * svd.matrixV().transpose();
    if (!defNext.isApprox(mp->m_defElastic * mp->m_defPlastic)) {
      logger->warn("Deformation update is incorrect");
    }
  }
}

void Simulator::updateParticleVelocities(double delta_t, float alpha) {
  for (auto &mp : m_materialPoints.particles()) {
    Vector3f velocityPIC = Vector3f::Zero();
    Vector3f velocityFLIP = mp->m_velocity;

    m_grid->forEachNeighbor(
        mp, [mp, &velocityPIC, &velocityFLIP](GridNode *node) {
          float weight = node->basisFunction(mp->m_position);

          velocityPIC += node->m_nextVelocity * weight;
          velocityFLIP += (node->m_nextVelocity - node->m_velocity) * weight;
        });

    mp->m_velocity = (1 - alpha) * velocityPIC + alpha * velocityFLIP;
  }
}

void Simulator::detectParticleCollisions(double delta_t) {
  for (auto &mp : m_materialPoints.particles()) {
    for (auto &collider : m_colliders) {
      Vector3f position = mp->m_position;
      if (collider->phi(position) > 0) {
        continue;
      }

      // std::cout << mp->position() << std::endl;

      Vector3f normal = collider->normal(position);
      Vector3f relVelocity = mp->velocity() - collider->velocity();

      // std::cout << collider->velocity() << std::endl;

      double magnitude = relVelocity.dot(normal);
      if (magnitude >= 0) {
        continue;
      }

      // std::cout << "GOT HERE" << std::endl;

      Vector3f tangentialVelocity = relVelocity - magnitude * normal;

      // Only apply dynamic friction if the tangential velocity is large
      // compared to the normal

      double normComponent = collider->friction() * magnitude;
      double tangentNorm = tangentialVelocity.norm();

      if (collider->sticky() || tangentNorm <= -normComponent) {
        relVelocity.setZero();
      } else {
        relVelocity = tangentialVelocity * (1 + normComponent / tangentNorm);
      }

      mp->m_velocity = relVelocity + collider->velocity();
    }
  }
}

/**
 * Uses backwards Euler integration to update the particle position for each
 * delta_t. At this point, the velocities should already have been updated
 * to the next delta_t.
 */
void Simulator::updateParticlePositions(double delta_t) {
  for (auto &mp : m_materialPoints.particles()) {
    mp->m_position += delta_t * mp->m_velocity;

    // mp->m_position = mp->m_position.array().min(
    //     (m_grid->m_dim.array()).cast<float>() * m_grid->m_spacing);
    // mp->m_position = mp->m_position.cwiseMax(0);
  }
}

std::string Simulator::exportVolumeData() {
  std::stringstream ss;
  ss << "../volumes/density-" << std::setfill('0') << std::setw(6)
     << m_stepCount << ".vol";

  std::ofstream os(ss.str());

  Vector3i dim = m_grid->dim();
  Vector3f bboxMin = m_grid->origin();
  Vector3f bboxMax = bboxMin + m_grid->extent();

  bboxMin = Vector3f(-0.5, -0.5, -0.5);
  bboxMax = Vector3f(0.5, 0.5, 0.5);

  os.write("VOL", 3);

  char version = 3;
  os.write((char *)&version, sizeof(char));

  int value = 1;
  os.write((char *)&value, sizeof(int));

  os.write((char *)&dim.x(), sizeof(int));
  os.write((char *)&dim.y(), sizeof(int));
  os.write((char *)&dim.z(), sizeof(int));

  value = 1;
  os.write((char *)&value, sizeof(int));

  os.write((char *)&bboxMin.x(), sizeof(float));
  os.write((char *)&bboxMin.y(), sizeof(float));
  os.write((char *)&bboxMin.z(), sizeof(float));

  os.write((char *)&bboxMax.x(), sizeof(float));
  os.write((char *)&bboxMax.y(), sizeof(float));
  os.write((char *)&bboxMax.z(), sizeof(float));

  auto nodes = m_grid->nodes();
  for (unsigned i = nodes.size(); i-- > 0;) {
    auto node = nodes[i];
    float value = (float)node->mass();
    os.write((char *)&value, sizeof(float));
  }

  return ss.str();
}

ext: cpp

max_stars_repo_name: kvchen/snowsim

max_issues_repo_name: kvchen/snowsim

max_forks_repo_name: kvchen/snowsim


text:
// zip.cpp
/*
 *  Copyright (c) 2007 Leigh Johnston.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 *     * Neither the name of Leigh Johnston nor the names of any
 *       other contributors to this software may be used to endorse or
 *       promote products derived from this software without specific prior
 *       written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 *  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 *  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.
*/

#include <neolib/neolib.hpp>
#include <fstream>
#include <string>
#include <zlib.h>
#include <boost/filesystem.hpp>
#include <neolib/core/string_utils.hpp>
#include <neolib/core/crc.hpp>
#include <neolib/file/zip.hpp>

#pragma pack(1)

namespace neolib
{
    namespace
    {
        template <typename T>
        inline const char* byte_cast(const T* p)
        {
            return reinterpret_cast<const char*>(p);
        }
    }

    struct zip::local_header
    {
        enum { Signature = 0x04034b50 };
        dword iSignature;
        word iVersion;
        word iFlag;
        word iCompression;
        word iTime;
        word iDate;
        dword iCrc32;
        dword iCompressedSize;
        dword iUncompressedSize;
        word iFilenameLength;
        word iExtraLength;
    };

    struct zip::dir_header
    {
        enum { Signature = 0x06054b50 };
        dword iSignature;
        word iDisk;
        word iStartDisk;
        word iDirEntries;
        word iTotalDirEntries;
        dword iDirSize;
        dword iDirOffset;
        word iCommentLength;
    };

    struct zip::dir_file_header
    {
        enum { Signature = 0x02014b50 };
        dword iSignature;
        word iVersionMade;
        word iVersionNeeded;
        word iFlag;
        word iCompression;
        word iTime;
        word iDate;
        dword iCrc32;
        dword iCompressedSize;
        dword iUncompressedSize;
        word iFilenameLength;
        word iExtraLength;
        word iCommentLength;
        word iDiskStart;
        word iIntAttr;
        dword iExtAttr;
        dword iHeaderOffset;
    };

    #pragma pack()

    zip::zip(const std::string& aZipFilePath) : iZipFileData{}, iZipFileDataLength{}, iError{false}
    {
        auto fileSize = boost::filesystem::file_size(aZipFilePath);
        if (fileSize > iZipFile.max_size())
            throw zip_file_too_big();
        iZipFile.resize(static_cast<std::size_t>(fileSize));
        iZipFileData = &iZipFile[0];
        iZipFileDataLength = iZipFile.size();
        std::ifstream input(aZipFilePath, std::ios::binary | std::ios::in);
        if (input.read(reinterpret_cast<char*>(&iZipFile[0]), iZipFile.size()))
            parse();
        else
            iError = true;
    }

    zip::zip(const buffer_type& aZipFile) : iZipFile{aZipFile}, iZipFileData{&iZipFile[0]}, iZipFileDataLength{iZipFile.size()}, iError{false}
    {
        parse();
    }

    zip::zip(buffer_type&& aZipFile) : iZipFile{std::move(aZipFile)}, iZipFileData{&iZipFile[0]}, iZipFileDataLength{iZipFile.size()}, iError{false}
    {
        parse();
    }

    zip::zip(const void* aZipFileData, std::size_t aZipFileDataLength) : iZipFileData{static_cast<const uint8_t*>(aZipFileData)}, iZipFileDataLength{aZipFileDataLength}, iError{ false }
    {
        parse();
    }

    std::size_t zip::index_of(const std::string& aFile) const
    {
        for (std::size_t i = 0; i < file_count(); ++i)
            if (file_path(i) == aFile)
                return i;
        throw file_not_found();
    }

    bool zip::extract(size_t aIndex, const std::string& aTargetDirectory)
    {
        buffer_type data;
        if (extract_to(aIndex, data))
        {
            std::ofstream out(aTargetDirectory + "/" + file_path(aIndex), std::ios::out | std::ios::binary);
            out.write(reinterpret_cast<const char*>(data[0]), data.size());
            if (out)
                return true;
        }
        iError = true;
        return false;
    }

    bool zip::extract_to(size_t aIndex, buffer_type& aBuffer)
    {
        if (iError)
            return false;
        if (aIndex > iFiles.size())
            return false;
        const local_header* lh = reinterpret_cast<const local_header*>(data_front() + iDirEntries[aIndex]->iHeaderOffset);
        if (byte_cast(lh) < byte_cast(data_front()) ||
            byte_cast(lh) > byte_cast(data_back()) - sizeof(local_header) + 1)
        {
            iError = true;
            return false;
        }
        if (lh->iSignature != local_header::Signature)
        {
            iError = true;
            return false;
        }
        const uint8_t* compressedData = reinterpret_cast<const uint8_t*>(lh + 1) + lh->iFilenameLength + lh->iExtraLength;
        if (byte_cast(compressedData) < byte_cast(data_front()) ||
            byte_cast(compressedData) + lh->iCompressedSize - 1 > byte_cast(data_back()))
        {
            iError = true;
            return false;
        }
        if (lh->iCompression == Z_NO_COMPRESSION)
        {
            if (crc32(reinterpret_cast<const uint8_t*>(compressedData), lh->iCompressedSize) != lh->iCrc32)
            {
                iError = true;
                return false;
            }
            aBuffer.resize(lh->iCompressedSize);
            std::copy(compressedData, compressedData + aBuffer.size(), &aBuffer[0]);
            return true;
        }
        else if (lh->iCompression != Z_DEFLATED)
        {
            iError = true;
            return false;
        }
        z_stream stream;
        stream.next_in = static_cast<Bytef*>(const_cast<uint8_t*>(compressedData));
        stream.avail_in = static_cast<uInt>(lh->iCompressedSize);
        aBuffer.resize(lh->iUncompressedSize);
        stream.next_out = static_cast<Bytef*>(&aBuffer[0]);
        stream.avail_out = static_cast<uInt>(aBuffer.size());
        stream.zalloc = static_cast<alloc_func>(0);
        stream.zfree = static_cast<free_func>(0);
        int result = inflateInit2(&stream, -MAX_WBITS);
        if (result == Z_OK)
        {
            result = inflate(&stream, Z_FINISH);
            inflateEnd(&stream);
            if (result == Z_STREAM_END)
                result = Z_OK;
            inflateEnd(&stream);
        }
        if (result != Z_OK)
        {
            iError = true;
            return false;
        }
        if (crc32(reinterpret_cast<const uint8_t*>(&aBuffer[0]), static_cast<uint32_t>(aBuffer.size())) != lh->iCrc32)
        {
            iError = true;
            return false;
        }
        return true;
    }

    std::string zip::extract_to_string(size_t aIndex)
    {
        buffer_type buffer;
        extract_to(aIndex, buffer);
        return std::string(buffer.begin(), buffer.end());
    }

    const std::string& zip::file_path(size_t aIndex) const
    {
        return iFiles[aIndex];
    }

    bool zip::parse()
    {
        if (iZipFileDataLength < sizeof(dir_header))
        {
            iError = true;
            return false;
        }
        const dir_header* dh = reinterpret_cast<const dir_header*>(data_back() - sizeof(dir_header) + 1);
        if (dh->iSignature != dir_header::Signature)
        {
            iError = true;
            return false;
        }
        const dir_file_header* fh = reinterpret_cast<const dir_file_header*>(data_back() - (dh->iDirSize + sizeof(dir_header)) + 1);
        for (size_t i = 0; i < dh->iDirEntries; ++i)
        {
            if (byte_cast(fh) < byte_cast(data_front()) ||
                byte_cast(fh) + sizeof(fh->iSignature) >= byte_cast(dh))
            {
                iError = false;
                return false;
            }
            if (fh->iSignature != dir_file_header::Signature)
            {
                iError = false;
                return false;
            }
            else
            {
                if (byte_cast(reinterpret_cast<const char*>(fh) + sizeof(*fh) + fh->iFilenameLength + fh->iExtraLength + fh->iCommentLength) >
                    byte_cast(dh))
                {
                    iError = false;
                    return false;
                }
                iDirEntries.push_back(fh);
                std::string filename(reinterpret_cast<const char*>(fh + 1), fh->iFilenameLength);
                iFiles.push_back(filename);
                fh = reinterpret_cast<const dir_file_header*>(reinterpret_cast<const char*>(fh) + sizeof(*fh) + fh->iFilenameLength + fh->iExtraLength + fh->iCommentLength);
            }
        }
        return true;
    }

    const uint8_t* zip::data_front()
    {
        return iZipFileData;
    }

    const uint8_t* zip::data_back()
    {
        return (iZipFileData + iZipFileDataLength - 1);
    }
}

max_stars_repo_name: madebr/neolib

max_issues_repo_name: madebr/neolib

max_forks_repo_name: madebr/neolib


text:
// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <cryptolink.h>
#include <cryptolink/crypto_hmac.h>

#include <boost/scoped_ptr.hpp>

#include <cstring>

namespace isc {
namespace cryptolink {

void
signHMAC(const void* data, const size_t data_len, const void* secret,
         size_t secret_len, const HashAlgorithm hash_algorithm,
         isc::util::OutputBuffer& result, size_t len)
{
    boost::scoped_ptr<HMAC> hmac(
        CryptoLink::getCryptoLink().createHMAC(secret,
                                               secret_len,
                                               hash_algorithm));
    hmac->update(data, data_len);
    if (len == 0) {
        len = hmac->getOutputLength();
    }
    hmac->sign(result, len);
}

bool
verifyHMAC(const void* data, const size_t data_len, const void* secret,
           size_t secret_len, const HashAlgorithm hash_algorithm,
           const void* sig, const size_t sig_len)
{
    boost::scoped_ptr<HMAC> hmac(
        CryptoLink::getCryptoLink().createHMAC(secret,
                                               secret_len,
                                               hash_algorithm));
    hmac->update(data, data_len);
    size_t len = sig_len;
    if (len == 0) {
        len = hmac->getOutputLength();
    }
    return (hmac->verify(sig, len));
}

void
deleteHMAC(HMAC* hmac) {
    delete hmac;
}

} // namespace cryptolink
} // namespace isc

max_stars_repo_name: sebschrader/debian-pkg-isc-kea

max_issues_repo_name: sebschrader/debian-pkg-isc-kea

max_forks_repo_name: sebschrader/debian-pkg-isc-kea


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

#include <gtest/gtest.h>

#include <Eigen/Core>
#include <smooth/so3.hpp>

#include "smooth/feedback/collocation/mesh_function.hpp"

using namespace Eigen;

/// Reduce a hstacked Hessian (as returned by smooth::diff) with multipliers
MatrixXd blocksum(const VectorXd & lambda, const MatrixXd & in)
{
  MatrixXd ret = MatrixXd::Zero(in.rows(), in.rows());
  for (auto i = 0u; i < lambda.size(); ++i) {
    ret += lambda(i) * in.block(0, i * in.rows(), in.rows(), in.rows());
  }
  return ret;
}

/// Sample analytic mesh function (does not allocate)
struct Functor
{
  SparseMatrix<double> jac, hess;

  Functor()
  {
    jac.resize(3, 6);

    jac.coeffRef(0, 0) = 0.;
    jac.coeffRef(0, 1) = 0.;
    jac.coeffRef(0, 5) = 0.;

    jac.coeffRef(1, 3) = 0.;

    jac.coeffRef(2, 0) = 0.;
    jac.coeffRef(2, 2) = 0.;
    jac.coeffRef(2, 4) = 0.;

    jac.makeCompressed();

    hess.resize(6, 3 * 6);

    hess.coeffRef(0, 0 * 6 + 1) = 0;
    hess.coeffRef(0, 0 * 6 + 5) = 0;

    hess.coeffRef(1, 0 * 6 + 0) = 0;
    hess.coeffRef(1, 0 * 6 + 1) = 0;
    hess.coeffRef(1, 0 * 6 + 5) = 0;

    hess.coeffRef(5, 0 * 6 + 0) = 0;
    hess.coeffRef(5, 0 * 6 + 1) = 0;

    // second component

    hess.coeffRef(3, 1 * 6 + 3) = 0;

    // third component

    hess.coeffRef(0, 2 * 6 + 0) = 0;
    hess.coeffRef(0, 2 * 6 + 2) = 0;
    hess.coeffRef(0, 2 * 6 + 4) = 0;

    hess.coeffRef(2, 2 * 6 + 0) = 0;
    hess.coeffRef(2, 2 * 6 + 4) = 0;

    hess.coeffRef(4, 2 * 6 + 0) = 0;
    hess.coeffRef(4, 2 * 6 + 2) = 0;

    hess.makeCompressed();
  }

  template<typename T>
  Vector3<T> operator()(T t, const Vector3<T> & x, const Vector2<T> & u)
  {
    return Vector3<T>{
      t * x.x() * x.x() * u.y(),
      x.z() * x.z(),
      t * t * x.y() * u.x(),
    };
  }

  const SparseMatrix<double> & jacobian(double t, const Vector3d & x, const Vector2d & u)
  {
    jac.coeffRef(0, 0) = x.x() * x.x() * u.y();  // df0 / dt
    jac.coeffRef(0, 1) = t * 2 * x.x() * u.y();  // df0 / dx0
    jac.coeffRef(0, 5) = t * x.x() * x.x();      // df0 / du1

    jac.coeffRef(1, 3) = 2 * x.z();  // df1 / dx2

    jac.coeffRef(2, 0) = 2 * t * x.y() * u.x();  // df2 / dt
    jac.coeffRef(2, 2) = t * t * u.x();          // df2 / dx1
    jac.coeffRef(2, 4) = t * t * x.y();          // df2 / du1

    assert(jac.isCompressed());

    return jac;
  }

  const SparseMatrix<double> & hessian(double t, const Vector3d & x, const Vector2d & u)
  {
    // first component

    hess.coeffRef(0, 0 * 6 + 1) = 2 * x.x() * u.y();  // d2f0 / dtx0
    hess.coeffRef(0, 0 * 6 + 5) = x.x() * x.x();      // d2f0 / dtu1

    hess.coeffRef(1, 0 * 6 + 0) = 2 * x.x() * u.y();  // d2f0 / dx0t
    hess.coeffRef(1, 0 * 6 + 1) = 2 * t * u.y();      // d2f0 / dx0x0
    hess.coeffRef(1, 0 * 6 + 5) = 2 * t * x.x();      // d2f0 / dx0u1

    hess.coeffRef(5, 0 * 6 + 0) = x.x() * x.x();  // d2f0 / du1t
    hess.coeffRef(5, 0 * 6 + 1) = 2 * t * x.x();  // d2f0 / du1x0

    // second component

    hess.coeffRef(3, 1 * 6 + 3) = 2;  // d2f1 / dx2x2

    // third component

    hess.coeffRef(0, 2 * 6 + 0) = 2 * x.y() * u.x();  // d2f2 / dtt
    hess.coeffRef(0, 2 * 6 + 2) = 2 * t * u.x();      // d2f2 / dtx1
    hess.coeffRef(0, 2 * 6 + 4) = 2 * t * x.y();      // d2f2 / dtu0

    hess.coeffRef(2, 2 * 6 + 0) = 2 * t * u.x();  // d2f2 / dx1t
    hess.coeffRef(2, 2 * 6 + 4) = t * t;          // d2f2 / dx1u0

    hess.coeffRef(4, 2 * 6 + 0) = 2 * t * x.y();  // d2f2 / du0t
    hess.coeffRef(4, 2 * 6 + 2) = t * t;          // d2f2 / du0x1

    assert(hess.isCompressed());

    return hess;
  }
};

class MeshFunction_Random : public testing::Test
{
protected:
  Functor f{};

  static constexpr int nx = 3, nu = 2;

  // mesh
  std::size_t N;
  smooth::feedback::Mesh<4, 6> mesh;

  // variables
  double t0 = 1;
  double tf = 6;

  Matrix<double, nx, -1> X;
  Matrix<double, nu, -1> U;

  VectorXd xflat;
  VectorXd uflat;

  void SetUp() override
  {
    mesh.refine_ph(0, 8);
    mesh.refine_ph(0, 5);

    N = mesh.N_colloc();

    X.setRandom(nx, N + 1);
    U.setRandom(nu, N);

    xflat = X.reshaped();
    uflat = U.reshaped();
  }
};

TEST_F(MeshFunction_Random, TestTheTest)
{
  const double t                    = 1;
  const Eigen::Vector<double, nx> x = Eigen::Vector<double, nx>::Random();
  const Eigen::Vector<double, nu> u = Eigen::Vector<double, nu>::Random();

  const auto [fn, dfn, d2fn] = smooth::diff::dr<2>(f, smooth::wrt(t, x, u));
  const auto [fa, dfa, d2fa] =
    smooth::diff::dr<2, smooth::diff::Type::Analytic>(f, smooth::wrt(t, x, u));

  ASSERT_TRUE(fn.isApprox(fa));
  ASSERT_TRUE(dfn.isApprox(Eigen::MatrixXd(dfa), 1e-3));
  ASSERT_TRUE(d2fn.isApprox(Eigen::MatrixXd(d2fa), 1e-3));
}

TEST_F(MeshFunction_Random, EvalDerivative)
{
  using namespace smooth;

  // numerical derivatives of function
  auto fd =
    [&](double t0var, double tfvar, const VectorXd & xvar, const VectorXd & uvar) -> VectorXd {
    Eigen::Matrix<double, nx, -1> Xvar = xvar.reshaped(nx, N + 1);
    Eigen::Matrix<double, nu, -1> Uvar = uvar.reshaped(nu, N);
    feedback::MeshValue<0> o;
    feedback::mesh_eval(o, mesh, f, t0var, tfvar, Xvar.colwise(), Uvar.colwise());
    return o.F;
  };
  auto [fval, dfval, d2fval] = diff::dr<2, diff::Type::Numerical>(fd, wrt(t0, tf, xflat, uflat));

  // numerical derivative of jacobian
  auto fdj =
    [&](double t0var, double tfvar, const VectorXd & xvar, const VectorXd & uvar) -> VectorXd {
    Eigen::Matrix<double, nx, -1> Xvar = xvar.reshaped(nx, N + 1);
    Eigen::Matrix<double, nu, -1> Uvar = uvar.reshaped(nu, N);
    feedback::MeshValue<1> o;
    // NOTE: can not double-differentiate!
    feedback::mesh_eval<1, diff::Type::Analytic>(
      o, mesh, f, t0var, tfvar, Xvar.colwise(), Uvar.colwise());
    return Eigen::MatrixXd(o.dF).transpose().reshaped();
  };
  auto [u0_, d2fval_j] = diff::dr<1, diff::Type::Numerical>(fdj, wrt(t0, tf, xflat, uflat));

  // analytic (analytic inner)
  {
    feedback::MeshValue<2> out;
    out.lambda.setRandom(nx * N);
    feedback::mesh_eval<2, diff::Type::Analytic>(out, mesh, f, t0, tf, X.colwise(), U.colwise());

    // compare values
    ASSERT_TRUE(MatrixXd(out.dF).isApprox(dfval, 1e-3));

    MatrixXd hess = MatrixXd(out.d2F).selfadjointView<Upper>();
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval), 1e-3));
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval_j.transpose()), 1e-3));
  }

  // analytic (numerical inner)
  {
    feedback::MeshValue<2> out;
    out.lambda.setRandom(nx * N);
    feedback::mesh_eval<2, diff::Type::Numerical>(out, mesh, f, t0, tf, X.colwise(), U.colwise());

    // compare values
    ASSERT_TRUE(MatrixXd(out.dF).isApprox(dfval, 1e-3));

    MatrixXd hess = MatrixXd(out.d2F).selfadjointView<Upper>();
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval), 1e-3));
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval_j.transpose()), 1e-3));
  }
}

TEST_F(MeshFunction_Random, IntegralDerivative)
{
  using namespace smooth;

  // numerical derivative of function
  auto fd =
    [&](double t0var, double tfvar, const VectorXd & xvar, const VectorXd & uvar) -> VectorXd {
    Eigen::Matrix<double, nx, -1> Xvar = xvar.reshaped(nx, N + 1);
    Eigen::Matrix<double, nu, -1> Uvar = uvar.reshaped(nu, N);
    feedback::MeshValue<0> o;
    feedback::mesh_integrate(o, mesh, f, t0var, tfvar, Xvar.colwise(), Uvar.colwise());
    return o.F;
  };
  auto [fval, dfval, d2fval] = diff::dr<2>(fd, wrt(t0, tf, xflat, uflat));

  // numerical derivative of jacobian
  auto fdj =
    [&](double t0var, double tfvar, const VectorXd & xvar, const VectorXd & uvar) -> VectorXd {
    Eigen::Matrix<double, nx, -1> Xvar = xvar.reshaped(nx, N + 1);
    Eigen::Matrix<double, nu, -1> Uvar = uvar.reshaped(nu, N);
    feedback::MeshValue<1> o;
    // NOTE: can not double-differentiate!
    feedback::mesh_integrate<1, diff::Type::Analytic>(
      o, mesh, f, t0var, tfvar, Xvar.colwise(), Uvar.colwise());
    return Eigen::MatrixXd(o.dF).transpose().reshaped();
  };
  auto [u0_, d2fval_j] = diff::dr<1, diff::Type::Numerical>(fdj, wrt(t0, tf, xflat, uflat));

  // analytic (analytic inner)
  {
    feedback::MeshValue<2> out;
    out.lambda.setRandom(nx);
    feedback::mesh_integrate<2, diff::Type::Analytic>(
      out, mesh, f, t0, tf, X.colwise(), U.colwise());

    // compare values
    ASSERT_TRUE(MatrixXd(out.dF).isApprox(dfval, 1e-3));
    MatrixXd hess = MatrixXd(out.d2F).selfadjointView<Upper>();
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval), 1e-3));
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval_j.transpose()), 1e-3));
  }

  // analytic (numerical inner)
  {
    feedback::MeshValue<2> out;
    out.lambda.setRandom(nx);
    feedback::mesh_integrate<2, diff::Type::Numerical>(
      out, mesh, f, t0, tf, X.colwise(), U.colwise());

    // compare values
    ASSERT_TRUE(MatrixXd(out.dF).isApprox(dfval, 1e-3));
    MatrixXd hess = MatrixXd(out.d2F).selfadjointView<Upper>();
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval), 1e-3));
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval_j.transpose()), 1e-3));
  }
}

TEST_F(MeshFunction_Random, DynDerivative)
{
  using namespace smooth;

  // numerical derivative of function
  auto fd =
    [&](double t0var, double tfvar, const VectorXd & xvar, const VectorXd & uvar) -> VectorXd {
    Eigen::Matrix<double, nx, -1> Xvar = xvar.reshaped(nx, N + 1);
    Eigen::Matrix<double, nu, -1> Uvar = uvar.reshaped(nu, N);
    feedback::MeshValue<0> o;
    feedback::mesh_dyn(o, mesh, f, t0var, tfvar, Xvar.colwise(), Uvar.colwise());
    return o.F;
  };
  auto [fval, dfval, d2fval] = diff::dr<2, diff::Type::Numerical>(fd, wrt(t0, tf, xflat, uflat));

  // numerical derivative of jacobian
  auto fdj =
    [&](double t0var, double tfvar, const VectorXd & xvar, const VectorXd & uvar) -> VectorXd {
    Eigen::Matrix<double, nx, -1> Xvar = xvar.reshaped(nx, N + 1);
    Eigen::Matrix<double, nu, -1> Uvar = uvar.reshaped(nu, N);
    feedback::MeshValue<1> o;
    // NOTE: can not double-differentiate with Numerical!
    feedback::mesh_dyn<1, diff::Type::Analytic>(
      o, mesh, f, t0var, tfvar, Xvar.colwise(), Uvar.colwise());
    return Eigen::MatrixXd(o.dF).transpose().reshaped();
  };
  auto [u0_, d2fval_j] = diff::dr<1, diff::Type::Numerical>(fdj, wrt(t0, tf, xflat, uflat));

  // analytic (analytic inner)
  {
    feedback::MeshValue<2> out;
    out.lambda.setRandom(nx * N);
    feedback::mesh_dyn<2, diff::Type::Analytic>(out, mesh, f, t0, tf, X.colwise(), U.colwise());

    // compare values
    ASSERT_TRUE(MatrixXd(out.dF).isApprox(dfval, 1e-3));
    MatrixXd hess = MatrixXd(out.d2F).selfadjointView<Upper>();
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval), 1e-3));
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval_j.transpose()), 1e-3));
  }

  // analytic (numerical inner)
  {
    feedback::MeshValue<2> out;
    out.lambda.setRandom(nx * N);
    feedback::mesh_dyn<2, diff::Type::Numerical>(out, mesh, f, t0, tf, X.colwise(), U.colwise());

    // compare values
    ASSERT_TRUE(MatrixXd(out.dF).isApprox(dfval, 1e-3));
    MatrixXd hess = MatrixXd(out.d2F).selfadjointView<Upper>();
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval), 1e-3));
    ASSERT_TRUE(hess.isApprox(blocksum(out.lambda, d2fval_j.transpose()), 1e-3));
  }
}

TEST_F(MeshFunction_Random, EvalAllocationAnalytic)
{
  smooth::feedback::MeshValue<2> out;
  out.lambda.setRandom(nx * N);

  // first call: not allocated
  ASSERT_FALSE(out.allocated);
  smooth::feedback::mesh_eval<2, smooth::diff::Type::Analytic>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  ASSERT_FALSE(out.dF.isCompressed());
  ASSERT_FALSE(out.d2F.isCompressed());

  out.dF.makeCompressed();
  out.d2F.makeCompressed();

  // second call: allocated
  ASSERT_TRUE(out.allocated);
  smooth::feedback::mesh_eval<2, smooth::diff::Type::Analytic>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  // expect to still be compressed (means we only touched existing coeffs)
  ASSERT_TRUE(out.dF.isCompressed());
  ASSERT_TRUE(out.d2F.isCompressed());
}

TEST_F(MeshFunction_Random, EvalAllocationNumerical)
{
  smooth::feedback::MeshValue<2> out;
  out.lambda.setRandom(nx * N);

  // first call: not allocated
  ASSERT_FALSE(out.allocated);
  smooth::feedback::mesh_eval<2, smooth::diff::Type::Numerical>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  ASSERT_FALSE(out.dF.isCompressed());
  ASSERT_FALSE(out.d2F.isCompressed());

  out.dF.makeCompressed();
  out.d2F.makeCompressed();

  // numerical eval gives non-sparse derivatives, so we expect all allocated memory to be used
  ASSERT_EQ(out.dF.nonZeros(), out.dF.data().size());
  ASSERT_EQ(out.d2F.nonZeros(), out.d2F.data().size());

  // second call: allocated
  ASSERT_TRUE(out.allocated);
  smooth::feedback::mesh_eval<2, smooth::diff::Type::Numerical>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  // expect to still be compressed (means we only touched existing coeffs)
  ASSERT_TRUE(out.dF.isCompressed());
  ASSERT_TRUE(out.d2F.isCompressed());
}

TEST_F(MeshFunction_Random, IntegrateAllocationAnalytic)
{
  smooth::feedback::MeshValue<2> out;
  out.lambda.setRandom(nx);

  // first call: not allocated
  ASSERT_FALSE(out.allocated);
  smooth::feedback::mesh_integrate<2, smooth::diff::Type::Analytic>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  ASSERT_FALSE(out.dF.isCompressed());
  ASSERT_FALSE(out.d2F.isCompressed());

  out.dF.makeCompressed();
  out.d2F.makeCompressed();

  // second call: allocated
  ASSERT_TRUE(out.allocated);
  smooth::feedback::mesh_integrate<2, smooth::diff::Type::Analytic>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  // expect to still be compressed (means we only touched existing coeffs)
  ASSERT_TRUE(out.dF.isCompressed());
  ASSERT_TRUE(out.d2F.isCompressed());
}

TEST_F(MeshFunction_Random, IntegrateAllocationNumerical)
{
  smooth::feedback::MeshValue<2> out;
  out.lambda.setRandom(nx);

  // first call: not allocated
  ASSERT_FALSE(out.allocated);
  smooth::feedback::mesh_integrate<2, smooth::diff::Type::Numerical>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  ASSERT_FALSE(out.dF.isCompressed());
  ASSERT_FALSE(out.d2F.isCompressed());

  // numerical eval gives non-sparse derivatives, so we expect all allocated memory to be used
  ASSERT_EQ(out.dF.nonZeros(), out.dF.data().size());
  ASSERT_EQ(out.d2F.nonZeros(), out.d2F.data().size());

  out.dF.makeCompressed();
  out.d2F.makeCompressed();

  // second call: allocated
  ASSERT_TRUE(out.allocated);
  smooth::feedback::mesh_integrate<2, smooth::diff::Type::Numerical>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  // expect to still be compressed (means we only touched existing coeffs)
  ASSERT_TRUE(out.dF.isCompressed());
  ASSERT_TRUE(out.d2F.isCompressed());
}

TEST_F(MeshFunction_Random, DynAllocationAnalytic)
{
  smooth::feedback::MeshValue<2> out;
  out.lambda.setRandom(nx * N);

  // first call: not allocated
  ASSERT_FALSE(out.allocated);
  smooth::feedback::mesh_dyn<2, smooth::diff::Type::Analytic>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  ASSERT_FALSE(out.dF.isCompressed());
  ASSERT_FALSE(out.d2F.isCompressed());

  out.dF.makeCompressed();
  out.d2F.makeCompressed();

  // second call: allocated
  ASSERT_TRUE(out.allocated);
  smooth::feedback::mesh_dyn<2, smooth::diff::Type::Analytic>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  // expect to still be compressed (means we only touched existing coeffs)
  ASSERT_TRUE(out.dF.isCompressed());
  ASSERT_TRUE(out.d2F.isCompressed());
}

TEST_F(MeshFunction_Random, DynAllocationNumerical)
{
  smooth::feedback::MeshValue<2> out;
  out.lambda.setRandom(nx * N);

  // first call: not allocated
  ASSERT_FALSE(out.allocated);
  smooth::feedback::mesh_dyn<2, smooth::diff::Type::Numerical>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  ASSERT_FALSE(out.dF.isCompressed());
  ASSERT_FALSE(out.d2F.isCompressed());

  // numerical eval gives non-sparse derivatives, so we expect all allocated memory to be used
  ASSERT_EQ(out.dF.nonZeros(), out.dF.data().size());
  ASSERT_EQ(out.d2F.nonZeros(), out.d2F.data().size());

  out.dF.makeCompressed();
  out.d2F.makeCompressed();

  // second call: allocated
  ASSERT_TRUE(out.allocated);
  smooth::feedback::mesh_dyn<2, smooth::diff::Type::Numerical>(
    out, mesh, f, t0, tf, X.colwise(), U.colwise());

  // expect to still be compressed (means we only touched existing coeffs)
  ASSERT_TRUE(out.dF.isCompressed());
  ASSERT_TRUE(out.d2F.isCompressed());
}

/**
 * @brief Test using time-defined trajectory x(t) = 0.1 t^2 - 0.4 t + 0.2
 */
class MeshFunction_Traj1 : public testing::Test
{
protected:
  static constexpr std::size_t nx = 1, nu = 0, nq = 1;

  static constexpr auto df_dt =
    []<typename T>(const T & t, const Vector<T, nx> &, const Vector<T, nu> &) -> Vector<T, nx> {
    return Vector<T, nx>{{0.2 * t - 0.4}};
  };

  // variables
  const double t0 = 3, tf = 5;
  Matrix<double, nx, -1> X;
  Matrix<double, nu, -1> U;

  // mesh
  smooth::feedback::Mesh<5, 5> m;

  void SetUp() override
  {
    m.refine_ph(0, 40);
    const auto N = m.N_colloc();

    X.setRandom(nx, N + 1);
    U.setRandom(nu, N);

    for (const auto & [i, tau] : smooth::utils::zip(std::views::iota(0u), m.all_nodes())) {
      const auto s = t0 + (tf - t0) * tau;
      X(i)         = 0.1 * s * s - 0.4 * s + 0.2;
    }
  }
};

TEST_F(MeshFunction_Traj1, Integral)
{
  const auto g =
    []<typename T>(const T &, const Vector<T, nx> & x, const Vector<T, nu> &) -> Vector<T, nq> {
    return Vector<T, nq>{{0.1 + x.squaredNorm()}};
  };

  smooth::feedback::MeshValue<0> out;
  smooth::feedback::mesh_integrate(out, m, g, t0, tf, X.colwise(), U.colwise());
  ASSERT_NEAR(out.F.x(), 0.217333 + 0.1 * (tf - t0), 1e-4);
}

TEST_F(MeshFunction_Traj1, Dynamics)
{
  smooth::feedback::MeshValue<1> out;
  smooth::feedback::mesh_dyn<1>(out, m, df_dt, t0, tf, X.colwise(), U.colwise());

  ASSERT_LE(out.F.cwiseAbs().maxCoeff(), 1e-8);
}

/**
 * @brief Test using time-defined trajectory x(t) = 1.5 exp(-t)
 */
class MeshFunction_Traj2 : public testing::Test
{
protected:
  static constexpr std::size_t nx = 1, nu = 0, nq = 1;

  static constexpr auto df_dt =
    []<typename T>(const T &, const Vector<T, nx> & x, const Vector<T, nu> &) -> Vector<T, nx> {
    return Vector<T, nx>{{-x.x()}};
  };

  // variables
  const double t0 = 3, tf = 5;
  Matrix<double, nx, -1> X;
  Matrix<double, nu, -1> U;

  // mesh
  smooth::feedback::Mesh<5, 5> m;

  void SetUp() override
  {
    m.refine_ph(0, 40);
    const auto N = m.N_colloc();

    X.setRandom(nx, N + 1);
    U.setRandom(nu, N);

    for (const auto & [i, tau] : smooth::utils::zip(std::views::iota(0u), m.all_nodes())) {
      const auto s = t0 + (tf - t0) * tau;
      X(i)         = 1.5 * exp(-s);
    }
  }
};

TEST_F(MeshFunction_Traj2, Integral)
{
  const auto g =
    []<typename T>(const T &, const Vector<T, nx> & x, const Vector<T, nu> &) -> Vector<T, nq> {
    return Vector<T, nq>{{x.squaredNorm()}};
  };

  smooth::feedback::MeshValue<0> out;
  smooth::feedback::mesh_integrate(out, m, g, t0, tf, X.colwise(), U.colwise());
  ASSERT_NEAR(out.F.x(), 0.00273752, 1e-4);
}

TEST_F(MeshFunction_Traj2, Dynamics)
{
  smooth::feedback::MeshValue<1> out;
  smooth::feedback::mesh_dyn<1>(out, m, df_dt, t0, tf, X.colwise(), U.colwise());
  ASSERT_LE(out.F.cwiseAbs().maxCoeff(), 1e-8);
}


text:
#include "dynet/nodes.h"
#include "dynet/dynet.h"
#include "dynet/training.h"
#include "dynet/timing.h"
#include "dynet/dict.h"
#include "dynet/expr.h"

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

using namespace std;
using namespace dynet;

using namespace std;
using namespace dynet;
using namespace dynet::expr;

/*
debug
void Print (const vector<float>& v){
  //vector<int> v;
  for (int i=0; i<v.size();i++){
    cout << v[i] << endl;
  }
}*/

/*vector<string> read_lines(string file_name)
{
	vector<string> lines;
	ifstream myfile (file_name);
	string line;
	while (getline(myfile, line))
	{
		lines.push_back(line);
	}
}*/

int main(int argc, char** argv) {
	dynet::initialize(argc, argv); // need to add this apparently ??

	dynet::Dict d;
	//int start_sent 	= d.convert("<s>");
  	//int end_sent 	= d.convert("</s>");

  	// Read data
	vector<vector<int>> training;

	cout << "READING DATA" << endl;
	ifstream in("/home/slouvan/dynet/examples/example-data/fin-words.txt");
	string line;
	while(getline(in, line)) {
      training.push_back(read_sentence(line, &d));
      cout<< line << endl;
    }

	unsigned hidden_dim 		= 50;
	unsigned layer_input_dim 	= 10;
	unsigned VOCAB_SIZE 		= d.size();

	// Define parameters
	Model model;
	LookupParameter p_c = model.add_lookup_parameters(VOCAB_SIZE, {layer_input_dim});
	Parameter 		p_W = model.add_parameters({hidden_dim, layer_input_dim});
	Parameter 		p_U	= model.add_parameters({hidden_dim, hidden_dim});
	Parameter 		p_B = model.add_parameters({hidden_dim});
	Parameter 		p_V = model.add_parameters({VOCAB_SIZE, hidden_dim});

	// Add parameters to the graph
	ComputationGraph cg;
  	Expression W = parameter(cg, p_W);
  	Expression U = parameter(cg, p_U);
  	Expression b = parameter(cg, p_B);
  	Expression V = parameter(cg, p_V);

  	vector<Expression> h_t; // store previous hidden state

  	SimpleSGDTrainer trainer(&model, 0.1);

  	// TRAINING

  	for (unsigned i = 0; i < training.size(); ++i) {
  		vector<int> current_sent = training[i];

  		// for each training instance build the sequence
  		vector<Expression> h_t_1;
  		Expression h0; // how to init the first one?
  		for (unsigned t = 0; t < current_sent.size(); ++t)
  		{
  			Expression x_t = lookup(cg, p_c, current_sent[t]);	// input
  			Expression h_t;

  			if (t == 0) // the first time step
  			{
  				h_t = tanh(W * x_t + U * h0 + b);
  			}
  			else
  			{
  				h_t = tanh(W * x_t + U * h_t_1[t-1] + b);
  			}

  			// compute and sum error here

  			h_t_1.push_back(h_t); // store the hidden state
  		}

  		// Expression loss =
  		// cg.forward(loss);
  		// cg.backward(loss);
  		// trainer.update();

  	}
	return 0;
}

max_stars_repo_name: slouvan/dynet

max_issues_repo_name: slouvan/dynet

max_forks_repo_name: slouvan/dynet


text:
#include "Option.h"
#include <iostream>
#include "libutil/Util.h"
#include <boost/program_options.hpp>

using namespace std;

struct Option::implDesc {
	boost::program_options::options_description desc;
};

Option::Option()
	:pimpl(new implDesc{ boost::program_options::options_description("Options", getScreenSize().first) })
{
	// define
	using boost::program_options::value;
	pimpl->desc.add_options()
		("help,h", "Print help messages")
		("showInfo", value<bool>(&show)->default_value(true), "Print the initializing information")
		("gPath,i", value<string>(&gPath)->required(), "The folder for original graph (input).")
		("tgPath,o", value<string>(&tgPath)->required(), "The folder for temporal edge-based graphs (output).")
		("nSubject,n", value<int>(&nSubject)->default_value(0),
			"# of subjects to load (non-positive means load all).")
		("nSkip,s",value<int>(&nSkip)->default_value(0),"Skip the first <s> subjects (used for restart from failure).")
		("nGraph,g",value<int>(&nGraph)->default_value(0), "The number of graphs for each subject (0 means all)")
		("types,t",value<vector<int>>(&types)->multitoken()->default_value(vector<int>(),"{}"),
			"Accepted subject types. Left empty for all types.")
		("selfpoint,p",value<bool>(&show)->default_value(true),
			"Whether to allow a temporal motif with identical edges in consecutive snapshots")
		;
}
Option::~Option(){
	delete pimpl;
}

bool Option::parseInput(int argc, char* argv[]) {
	//parse
	bool flag_help = false;
	boost::program_options::variables_map var_map;
	try {
		boost::program_options::store(
			boost::program_options::parse_command_line(argc, argv, pimpl->desc), var_map);
		boost::program_options::notify(var_map);

		if(var_map.count("help")) {
			flag_help = true;
		}
	} catch(std::exception& excep) {
		cerr << "Error: " << excep.what() << "\n";
		flag_help = true;
	} catch(...) {
		cerr << "Exception of unknown type!\n";
		flag_help = true;
	}
	while(!flag_help) { // technique for condition checking
		flag_help = true;
		if(nSkip<0){
			cerr<<"Error: nSkip should be 0 or positive"<< "\n";
			break;
		}

		sortUpPath(gPath);
		sortUpPath(tgPath);
		flag_help = false;
		break;
	}

	if(true == flag_help) {
		cerr << pimpl->desc << endl;
		return false;
	}
	return true;
}

std::string& Option::sortUpPath(std::string & path)
{
	if(!path.empty() && path.back() != '/')
		path.push_back('/');
	return path;
}

max_stars_repo_name: yxtj/DEG

max_issues_repo_name: yxtj/DEG

max_forks_repo_name: yxtj/DEG


text:
/*
 * libasiotap - A portable TAP adapter extension for Boost::ASIO.
 * Copyright (C) 2010-2011 Julien KAUFFMANN <julien.kauffmann@freelan.org>
 *
 * This file is part of libasiotap.
 *
 * libasiotap 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.
 *
 * libasiotap 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, see
 * <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 * You must obey the GNU General Public License in all respects
 * for all of the code used other than OpenSSL.  If you modify
 * file(s) with this exception, you may extend this exception to your
 * version of the file(s), but you are not obligated to do so.  If you
 * do not wish to do so, delete this exception statement from your
 * version.  If you delete this exception statement from all source
 * files in the program, then also delete it here.
 *
 * If you intend to use libasiotap in a commercial software, please
 * contact me : we may arrange this for a small fee or no fee at all,
 * depending on the nature of your project.
 */

/**
 * \file arp_proxy.hpp
 * \author Julien KAUFFMANN <julien.kauffmann@freelan.org>
 * \brief An ARP proxy class.
 */

#ifndef ASIOTAP_OSI_ARP_PROXY_HPP
#define ASIOTAP_OSI_ARP_PROXY_HPP

#include "proxy.hpp"

#include "ethernet_filter.hpp"
#include "arp_filter.hpp"
#include "complex_filter.hpp"
#include "ethernet_address.hpp"

#include <boost/optional.hpp>

#include <map>

namespace asiotap
{
	namespace osi
	{
		/**
		 * \brief An ARP proxy class.
		 */
		template <>
		class proxy<arp_frame> : public _base_proxy<arp_frame>
		{
			public:

				/**
				 * \brief The Ethernet address type.
				 */
				typedef ethernet_address ethernet_address_type;

				/**
				 * \brief The entry type.
				 */
				typedef std::pair<boost::asio::ip::address_v4, ethernet_address_type> entry_type;

				/**
				 * \brief The ARP request callback type.
				 */
				typedef boost::function<bool (const boost::asio::ip::address_v4&, ethernet_address_type&)> arp_request_callback_type;

				/**
				 * \brief Create an ARP proxy.
				 */
				proxy() :
					m_arp_request_callback(0)
				{
				}

				/**
				 * \brief Add a proxy entry.
				 * \param entry The entry to add.
				 * \return If an entry for the specified logical address already exists, nothing is done and the call returns false. Otherwise, the call returns true.
				 */
				bool add_entry(const entry_type& entry);

				/**
				 * \brief Add a proxy entry.
				 * \param logical_address The logical address.
				 * \param hardware_address The hardware address.
				 * \return If an entry for the specified logical address already exists, nothing is done and the call returns false. Otherwise, the call returns true.
				 */
				bool add_entry(const boost::asio::ip::address_v4& logical_address, const ethernet_address_type& hardware_address);

				/**
				 * \brief Delete a proxy entry.
				 * \param logical_address The logical address.
				 * \return If an entry was deleted, true is returned. Otherwise, the call returns false.
				 */
				bool remove_entry(const boost::asio::ip::address_v4& logical_address);

				/**
				 * \brief Set the callback function when a ARP request is received.
				 * \param callback The callback function.
				 */
				void set_arp_request_callback(arp_request_callback_type callback);

				/**
				 * \brief Process a frame.
				 * \param ethernet_helper The ethernet layer.
				 * \param arp_helper The ARP layer.
				 * \param response_buffer The buffer to write the response to.
				 * \return The buffer that contains the answer, if there is one.
				 */
				boost::optional<boost::asio::const_buffer> process_frame(const_helper<ethernet_frame> ethernet_helper, const_helper<arp_frame> arp_helper, boost::asio::mutable_buffer response_buffer) const;

			private:

				typedef std::map<boost::asio::ip::address_v4, ethernet_address_type> entry_map_type;

				entry_map_type m_entry_map;
				arp_request_callback_type m_arp_request_callback;
		};

		inline bool proxy<arp_frame>::add_entry(const entry_type& entry)
		{
			return m_entry_map.insert(entry).second;
		}

		inline bool proxy<arp_frame>::add_entry(const boost::asio::ip::address_v4& logical_address, const ethernet_address_type& hardware_address)
		{
			return add_entry(std::make_pair(logical_address, hardware_address));
		}

		inline bool proxy<arp_frame>::remove_entry(const boost::asio::ip::address_v4& logical_address)
		{
			return (m_entry_map.erase(logical_address) > 0);
		}

		inline void proxy<arp_frame>::set_arp_request_callback(arp_request_callback_type callback)
		{
			m_arp_request_callback = callback;
		}
	}
}

#endif /* ASIOTAP_ARP_PROXY_HPP */

max_stars_repo_name: krattai/AEBL

max_issues_repo_name: krattai/AEBL

max_forks_repo_name: krattai/AEBL


text:
// (C) Copyright Gert-Jan de Vos and Jan Wilmans 2013.
// 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)

// Repository at: https://github.com/djeedjay/DebugViewPP/

#include "stdafx.h"
#include <boost/filesystem.hpp>
#include "FileIO.h"
#include "FileReader.h"

namespace fusion {
namespace debugviewpp {

FileReader::FileReader(const std::wstring& filename) :
	m_end(false),
	m_filename(filename),
	m_name(Str(boost::filesystem::wpath(filename).filename().string()).str()),
	m_handle(FindFirstChangeNotification(boost::filesystem::wpath(m_filename).parent_path().wstring().c_str(), false, FILE_NOTIFY_CHANGE_SIZE)),
	m_thread(&FileReader::Run, this)
{
}

FileReader::~FileReader()
{
	Abort();
}

void FileReader::Abort()
{
	m_end = true;
	m_thread.join();
}

bool FileReader::AtEnd() const
{
	return false;
}

HANDLE FileReader::GetHandle() const
{
	return 0;	// todo::implement
}

void FileReader::Notify()
{
	// add a line to CircularBuffer
}

void FileReader::Run()
{
	std::ifstream ifs(m_filename);
	if (ifs.is_open())
	{
		std::string line;
		for (;;)
		{
			while (std::getline(ifs, line))
				Add(line);
			if (!ifs.eof())
			{
				// Some error other then EOF occured
				break;
			}
			ifs.clear(); // clear EOF condition
			bool signalled = WaitForSingleObject(m_handle.get(), 1000);
			if (m_end)
				break;
			if (signalled)
				FindNextChangeNotification(m_handle.get());
		}
	}
	Add(stringbuilder() << "Stopped tailing " << Str(m_filename));
}

void FileReader::Add(const std::string& text)
{
	Line line(m_timer.Get(), GetSystemTimeAsFileTime(), 0, boost::filesystem::wpath(m_filename).filename().string(), text);
	boost::unique_lock<boost::mutex> lock(m_linesMutex);
	m_buffer.push_back(line);
}

Lines FileReader::GetLines()
{
	Lines lines;
	boost::unique_lock<boost::mutex> lock(m_linesMutex);
	m_buffer.swap(lines);
	return lines;
}

DBLogReader::DBLogReader(const std::wstring& filename) :
	FileReader(filename),
	m_time(GetSystemTimeAsFileTime())
{
}

HANDLE DBLogReader::GetHandle() const
{
	return 0;	// todo::implement
}

void DBLogReader::Notify()
{
	// add a line to CircularBuffer
}

void DBLogReader::Add(const std::string& data)
{
	Line line = Line();
	line.systemTime = m_time;
	line.processName = m_name;
	ReadLogFileMessage(data, line);
	m_buffer.push_back(line);
}

} // namespace debugviewpp
} // namespace fusion

max_stars_repo_name: MarkGoldberg/DebugViewPP

max_issues_repo_name: MarkGoldberg/DebugViewPP

max_forks_repo_name: MarkGoldberg/DebugViewPP


text:
/*
 *  Copyright (C) 2004-2008 Christos Tsantilas
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA.
 */

#include <cstring>
#include <cerrno>

#include <c_icap/c-icap.h>
#include <c_icap/debug.h>
#include <c_icap/service.h>
#include <c_icap/header.h>
#include <c_icap/body.h>
#include <c_icap/simple_api.h>

#include "apiConnect.h"
#include "socket.h"
#include "tcpSocket.h"
#include "tcpCache.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#include <string>
#include <vector>
#include <iostream>
#include <sstream>

#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <boost/scoped_ptr.hpp>

#include "utils/loggingDevice.h"
#include "utils/assert.h"
#include "utils/urlNormalization.h"
#include "utils/foreach.h"
#include "utils/stringFunctions.h"
#include "utils/alerts.h"

namespace su = safekiddo::utils;

#ifdef NDEBUG
#define DEFAULT_LOG_LEVEL	"INFO"
#else
#define DEFAULT_LOG_LEVEL	"DEBUG1"
#endif

int safekiddo_init_service(ci_service_xdata_t * srv_xdata, struct ci_server_conf *server_conf);
int safekiddo_post_init_service(ci_service_xdata_t * srv_xdata, struct ci_server_conf *server_conf);
int safekiddo_check_preview_handler(char *preview_data, int preview_data_len, ci_request_t *);
int safekiddo_end_of_data_handler(ci_request_t * req);
void *safekiddo_init_request_data(ci_request_t * req);
void safekiddo_close_service();
void safekiddo_release_request_data(void *data);
int safekiddo_io(char *wbuf, int *wlen, char *rbuf, int *rlen, int iseof, ci_request_t * req);

/***********************************************************
 * SafeKiddo plugin configuration.
 *
 * Note: variables may be used not earlier than safekiddo_post_init_service().
 **********************************************************/
// LoggingDevice
static char const * confLogLevel = DEFAULT_LOG_LEVEL;
static char const * confLogFile = NULL;

// TcpCache
static char const * wsUrlAddress = NULL;
static int wsUrlPort = 80;
static int tcpCacheInactivityTime = 10000; // ms; must be lower than clientTimeout in httpd (currently 30s)
static int tcpCacheConnTimeout = 3000; // ms

// ApiConnect
static char const * confLogin = NULL;
static char const * confPassword = NULL;
static char const * confApiHost = NULL;
static char const * confDeviceUuid = NULL;
static char const * confChildUuid = NULL;

static ci_conf_entry configVariables[] = {
	// LoggingDevice
	{"LogLevel", &confLogLevel, ci_cfg_set_str, "log level"},
	{"LogFile", &confLogFile, ci_cfg_set_str, "log file path"},
	// TcpCache
	{"WsUrlAddress", &wsUrlAddress, ci_cfg_set_str, "WS URL host"},
	{"WsUrlPort", &wsUrlPort, ci_cfg_set_int, "WS URL tcp port"},
	{"TcpCacheInactivityTime", &tcpCacheInactivityTime, ci_cfg_set_int, "max inactivity time of a connection to WS URL"},
	{"TcpCacheConnTimeout", &tcpCacheConnTimeout, ci_cfg_set_int, "timeout for connecting to WS URL"},
	// ApiConnect
	{"Login", &confLogin, ci_cfg_set_str, "SafeKiddo account login"},
	{"Password", &confPassword, ci_cfg_set_str, "SafeKiddo account password"},
	{"ApiHost", &confApiHost, ci_cfg_set_str, "API host"},
	{"DeviceUuid", &confDeviceUuid, ci_cfg_set_str, "device uuid"},
	{"ChildUuid", &confChildUuid, ci_cfg_set_str, "child uuid"},
	{NULL, NULL, NULL, NULL}
};

CI_DECLARE_MOD_DATA ci_service_module_t service = {
	"safekiddo",                         /* mod_name, The module name */
	"Safekiddo service",                 /* mod_short_descr,  Module short description */
	ICAP_REQMOD,                         /* mod_type, The service type is responce or request modification */
	safekiddo_init_service,              /* mod_init_service. Service initialization */
	safekiddo_post_init_service,         /* mod_post_init_service. Service initialization after c-icap configured */
	safekiddo_close_service,             /* mod_close_service. Called when service shutdowns. */
	safekiddo_init_request_data,         /* mod_init_request_data */
	safekiddo_release_request_data,      /* mod_release_request_data */
	safekiddo_check_preview_handler,     /* mod_check_preview_handler */
	safekiddo_end_of_data_handler,       /* mod_end_of_data_handler */
	safekiddo_io,                        /* mod_service_io */
	configVariables,                     /* mod_conf_table */
	NULL                                 /* mod_data */
};

/* This function will be called when the service loaded  */
int safekiddo_init_service(ci_service_xdata_t * srv_xdata, struct ci_server_conf *server_conf)
{
	ci_service_set_preview(srv_xdata, 0);
	ci_service_enable_204(srv_xdata);
	ci_service_set_xopts(srv_xdata, CI_XAUTHENTICATEDUSER);
	return CI_OK;
}

static boost::optional<su::LogLevelEnum> logLevelEnumOpt;
static boost::scoped_ptr<utils::TcpCache> tcpCache;
static boost::scoped_ptr<utils::ApiConnect> apiConnect;

static std::string tryGetChildUuid()
{
	std::string childUuid = apiConnect->getChildUuid();
	if (childUuid.empty())
	{
		std::string cookie; // unused
		if (apiConnect->accessBlockedPage(cookie))
		{
			childUuid = apiConnect->getChildUuid();
		}
		else
		{
			LOG(WARNING, "Cannot access block page");
		}
		if (childUuid.empty())
		{
			LOG(ERROR, "Cannot obtain child uuid");
		}
	}
	return childUuid;
}

/*
 * Called just after forking a new child process of c-icap server. Requests are handled by child
 * processes. Parent process acts as a supervisor.
 */
static void fork_handler_child()
{
	ci_debug_printf(2, "creating LoggingDevice\n");

	std::string const logFilePath = std::string(confLogFile);
	su::LoggingDevice * loggingDevice = new su::FileLoggingDevice(logFilePath, logLevelEnumOpt.get());

	DASSERT(su::LoggingDevice::getImpl() == NULL, "LoggingDevice already set");
	su::LoggingDevice::setImpl(loggingDevice);
	loggingDevice->start();

	std::string const childUuid = tryGetChildUuid();
	if (!childUuid.empty())
	{
		LOG(INFO, "Starting with childUuid: " << childUuid);
	}
	else
	{
		// Crash in debug config if child uuid is not known.
		ALERT("Cannot obtain child uuid");
	}
}

static bool verifyStringParams()
{
	bool ret = true;
	for (size_t i = 0; i < sizeof(configVariables)/sizeof(configVariables[0]); ++i)
	{
		ci_conf_entry const & confEntry = configVariables[i];
		if (confEntry.action == ci_cfg_set_str)
		{
			char const * value = *static_cast<char const **>(confEntry.data);
			if (value == NULL)
			{
				std::cerr << "Error: missing safekiddo." << confEntry.name << " parameter\n";
				ret = false;
			}
		}
	}
	return ret;
}

// Don't use LOG here as LoggingDevice is set in child processes.
int safekiddo_post_init_service(ci_service_xdata_t * srv_xdata, struct ci_server_conf *server_conf)
{
	if (!verifyStringParams())
	{
		return CI_ERROR;
	}

	// LoggingDevice
	logLevelEnumOpt = su::LoggingDevice::parseLogLevel(confLogLevel);
	if (!logLevelEnumOpt)
	{
		std::cerr << "Error: invalid safekiddo.LogLevel argument: " << confLogLevel << "\n";
		return CI_ERROR;
	}

	// TcpCache
	// Constructor does not create new threads nor connections so is fork-safe.
	tcpCache.reset(new utils::TcpCache(wsUrlAddress, wsUrlPort, tcpCacheInactivityTime, tcpCacheConnTimeout));

	// ApiConnect
	// Constructor does not create new threads nor connections so is fork-safe.
	apiConnect.reset(new utils::ApiConnect(
		confLogin,
		confPassword,
		confApiHost,
		"/api/v1/",
		"login",
		"childs",
		"child/set",
		"block",
		confDeviceUuid,
		confChildUuid
	));

	ci_debug_printf(2, "installing fork handler\n");
	pthread_atfork(NULL, NULL, fork_handler_child);
	// Parent will not have LoggingDevice, but it is really needed only in children, which handle client requests.

	return CI_OK;
}

/* This function will be called when the service shutdown */
void safekiddo_close_service()
{
	apiConnect.reset();
	tcpCache.reset();

	su::LoggingDevice * loggingDevice = su::LoggingDevice::getImpl();
	if (loggingDevice)
	{
		ci_debug_printf(2, "destroying LoggingDevice\n");
		loggingDevice->stop();
		su::LoggingDevice::setImpl(NULL);
		delete loggingDevice;
	}
}

void printer(void*, const char *key, const char *value)
{
	DLOG(1, "HDR : " << key << ", VAL : " << value);
}

void safekiddo_print_request_headers(ci_request_t *req)
{
	ci_headers_iterate(req->request_header, NULL, printer);
}

const char *safekiddo_get_authenticated_user(ci_request_t *req)
{
//	safekiddo_print_request_headers(req);
	const char *key = "X-Authenticated-User: ";
	const char *hdr = ci_headers_search(req->request_header, key);
	if (!hdr)
	{
		return NULL;
	}
	return hdr + strlen(key);
}

struct body_data_t
{
	ci_ring_buf_t *body;
	int eof;
};

void *safekiddo_init_request_data(ci_request_t * req)
{
	struct body_data_t *body_data;

	/*Allocate memory fot the echo_data*/
	body_data = (body_data_t*) malloc(sizeof(struct body_data_t));
	if (!body_data)
	{
		ci_debug_printf(1, "Memory allocation failed inside safekiddo_init_request_data!\n");
		return NULL;
	}

	/*If the ICAP request encuspulates a HTTP objects which contains body data
	and not only headers allocate a ci_cached_file_t object to store the body data.
	*/
	if (ci_req_hasbody(req))
	{
		body_data->body = ci_ring_buf_new(4096);
	}
	else
	{
		body_data->body = NULL;
	}

	body_data->eof = 0;
	/*Return to the c-icap server the allocated data*/
	return body_data;
}

void safekiddo_release_request_data(void *data)
{
	struct body_data_t *body_data = (struct body_data_t *) data;

	if(body_data->body)
	{
		ci_ring_buf_destroy(body_data->body);
	}

	free(body_data);
}

/**
 * Function splits request in form: METHOD URL PROTOCOL (e.g. GET www.onet.pl HTTP/1.1) to
 * separate (sub)strings.
 */

static int splitRequest(
		const std::string &request, // original request string
		std::string &method, // will set to method name
		std::string &url, // will set to url
		std::string &proto) // will set to protocol string
{
	const size_t start = request.find(' ');
	if (start == std::string::npos)
	{
		return -1; // cannot find valid url start
	}

	const size_t end = request.rfind(' ');
	assert(end != std::string::npos);

	if (end == start || end == request.length() - 1) // end should not be the last element
	{
		return -1; // cannot find valud url end
	}
	// convert tail to lower case - that is why we have to check if 'end' is not at the end of the string
	proto = request.substr(end + 1);

	const std::string httpEnd = "http/1.";
	if (!su::isPrefixOfNoCase(httpEnd, proto))
	{
		return -1; // invalid request tail
	}

	method = request.substr(0, start);
	url = request.substr(start + 1, end - start - 1);

	return 0;
}

static inline bool contains(std::string const & str, char const * text)
{
	return str.find(text) != std::string::npos;
}

static std::vector<std::string> filterOutParamKeys(std::vector<std::string> const & params, char const * key)
{
	std::vector<std::string> result;

	FOREACH_CREF(param, params)
	{
		std::string decoded;
		su::percentDecode(param.substr(0, param.find('=')), decoded);
		if (decoded != key)
		{
			result.push_back(param);
		}
	}

	return result;
}

static boost::optional<std::string> modifyGoogleSearchUrl(std::string const & url)
{
	std::string protocolSpecification;
	std::string hostNameWithOptPort;
	std::string pathAndQueryString;
	std::string fragmentId;
	su::splitUrl(url, protocolSpecification, hostNameWithOptPort, pathAndQueryString, fragmentId);

	std::transform(hostNameWithOptPort.begin(), hostNameWithOptPort.end(), hostNameWithOptPort.begin(), ::tolower);
	if (!contains(hostNameWithOptPort, "google."))
	{
		return boost::none;
	}

	std::string path;
	std::vector<std::string> params;
	su::splitPathAndQueryString(pathAndQueryString, path, params);

	std::string decoded;
	su::percentDecode(path, decoded);
	// only lowercase works
	if (!contains(decoded, "/search"))
	{
		return boost::none;
	}

	char const * safeSearchKey = "safe";
	char const * safeSearchValue = "active";

	params = filterOutParamKeys(params, safeSearchKey);
	params.push_back(std::string(safeSearchKey) + "=" + safeSearchValue);

	return su::joinUrlParts(protocolSpecification, hostNameWithOptPort, path, params, fragmentId);
}

int writeWsRequest(boost::shared_ptr<utils::TcpSocket> sock,  std::string const & data, int timeout)
{
	char const * buf = data.c_str();
	size_t len = data.length();

	while (len)
	{
		ssize_t const wr = sock->write(buf, len);
		if (wr > 0)
		{
			len -= wr;
			buf += wr;
		}
		else
		{
			switch (wr)
			{
			case -EAGAIN:
			{
				int const res = sock->waitWrite(timeout);
				if (res == 1)
				{
					continue;
				}
				if (res == 0)
				{
					LOG(ERROR, "Timeout in write(): " << utils::sysError());
					return -1;
				}
				// fall through
			}
			default:
				LOG(ERROR, "Error in write(): " << utils::sysError());
				return -1;
			}
		}
	}

	return 0;
}

int readWsResponse(boost::shared_ptr<utils::TcpSocket> sock, int timeout)
{
	const size_t bufSize = 1023;
	char buf[bufSize + 1]; // we terminate with '\0'
	size_t inBuf = 0;
	buf[inBuf] = 0;

	while (true)
	{
		ssize_t const rd = sock->read(buf + inBuf, bufSize - inBuf);
		if (rd > 0)
		{
			inBuf += rd;
			buf[inBuf] = 0;
		}
		else
		{
			switch (rd)
			{
			case 0:
				LOG(ERROR, "WS URL aborted connection, data already received: '" << buf << "'");
				return -1;
			case -EAGAIN:
			{
				int const res = sock->waitRead(timeout);
				if (res == 1)
				{
					continue;
				}
				if (res == 0)
				{
					LOG(ERROR, "Timeout in read(): " << utils::sysError());
					return -1;
				}
				// fall through
			}
			default:
				LOG(ERROR, "Error in read(): " << utils::sysError());
				return -1;
			}
		}

		if (strstr(buf, "\nhack\n"))
		{
			break;
		}
	}

	char const * resultPrefix = "\nResult: ";

	char const * resultStart = strstr(buf, resultPrefix);
	if (resultStart == NULL)
	{
		LOG(ERROR, "No result in WS response", buf);
		return -1;
	}
	std::istringstream istr(resultStart + strlen(resultPrefix));
	int result;
	istr >> result;
	return result;
}

int wsRequest(const std::string &url, const std::string &user)
{
	if (user.empty())
	{
		LOG(WARNING, "User not known, not sending WS URL request", url);
		return 0;
	}

	DLOG(1, "Requesting ws: " << url);
	int const wsTimeout = 3000;
	bool const logging = false;
	std::stringstream sStream;

	std::string userAction = "";
	if(!logging)
	{
		userAction = "UserAction: 0\r\n";
	}

	// keep-alive by default in HTTP/1.1
	sStream << "GET /cc HTTP/1.1\r\nUserId: " << user << "\r\nRequest:" << url << "\r\nHost: " << tcpCache->getHostName() << "\r\n"
		<< userAction << "\r\n";

	boost::shared_ptr<utils::TcpSocket> socket = tcpCache->connect();
	if (!socket)
	{
		return -1;
	}

	if (writeWsRequest(socket, sStream.str(), wsTimeout))
	{
		return -1;
	}

	int const ret = readWsResponse(socket, wsTimeout);
	if (ret < 0)
	{
		LOG(ERROR, "Error in ws communication");
		return -1;
	}
	else
	{
		tcpCache->add(socket);
		return ret;
	}
}

int safekiddo_check_preview_handler(char * preview_data, int preview_data_len, ci_request_t * req)
{
	char const * authUser = safekiddo_get_authenticated_user(req);
	std::string const user = authUser ? std::string(authUser) : tryGetChildUuid();

	std::string url, method, proto;

	if (splitRequest(ci_http_request(req), method, url, proto))
	{
		LOG(ERROR, "Failed to parse http request '" << ci_http_request(req) << "'");
		return CI_MOD_ALLOW204;
	}
	if (strcasecmp(method.c_str(), "CONNECT") == 0)
	{
		DLOG(1, "Not altering CONNECT to '" << url << "'");
		return CI_MOD_ALLOW204;
	}

	DLOG(1, "User '" << user << "' requested url '" << url << "' method '" << method << "' proto '" << proto << "'");

	boost::optional<std::string> const modifiedUrl = modifyGoogleSearchUrl(url);
	int const wsUrlResult = wsRequest(url, user);

	bool const isSslRequest = su::isPrefixOfNoCase("https://", url);
	// Workaround for SAF-515: when using ssl-bump, ICAP request modification supports only HTTP urls. If different HTTPS url
	// is provided then no new connection is established by ssl-bump and we end up with a 404 from original target host.
	std::string const blockPageUrl = isSslRequest ? apiConnect->getBlockedPageUrlNoSsl() : apiConnect->getBlockedPageUrl();
	bool const isApiUrl = (url == blockPageUrl);

	if (modifiedUrl)
	{
		DLOG(1, "url modified: '" << url << "' => '" << modifiedUrl.get() << "'");
	}
	/* TODO: SAF-508 - parent requests don't work
	else if (isApiUrl)
	{
		DLOG(1, "request to a block page", url);
	}*/
	else if (wsUrlResult > 0)
	{
		LOG(INFO, "Access denied for user '" << user << "' result " << wsUrlResult << " url '" << url << "'");
	}
	else
	{
		return CI_MOD_ALLOW204;
	}

	ci_headers_list_t *list = ci_http_request_headers(req);

	std::vector<std::string> headers;
	for (int i = 0; i < list->used && list->headers[i] != NULL; ++i)
	{
		headers.push_back(list->headers[i]);
	}

	ci_http_request_reset_headers(req);
	std::string const requestStartsWith = method + " ";
	std::string const cookieHeaderPrefix = "Cookie: ";
	std::string const hostHeaderPrefix = "Host: ";

	FOREACH_CREF(header, headers)
	{
		if (su::isPrefixOf(requestStartsWith, header))
		{
			std::ostringstream request;
			// URL was dangerous, but after modification is safe
			if (modifiedUrl)
			{
				request << method << " " << modifiedUrl.get() << " " << proto;
				ci_http_request_add_header(req, request.str().c_str());
				DLOG(1, "request changed to: " << request.str());
			}
			else // URL is still dangerous - we have to block this page
			{
				if(isApiUrl)
				{
					request << method << url << " " << proto;
				}
				else
				{
					// redirect to block page
					request << "GET " << blockPageUrl << " " << proto;
				}
				ci_http_request_add_header(req, request.str().c_str());
				DLOG(1, "request changed to: " << request.str());

				std::string cookie;
				if (!apiConnect->accessBlockedPage(cookie))
				{
					LOG(WARNING, "Cannot access block page");
				}
				else
				{
					std::stringstream cookieHeaderStream;
					cookieHeaderStream << cookieHeaderPrefix << cookie;
					ci_http_request_add_header(req, cookieHeaderStream.str().c_str());
				}

				if(!isApiUrl)
				{
					// add params needed by block page
					std::stringstream skUrlStream;
					skUrlStream << "sk-url: " << url;
					ci_http_request_add_header(req, skUrlStream.str().c_str());

					DASSERT(wsUrlResult > 0, "why do we block this url?", wsUrlResult, url);
					std::stringstream skCodeStream;
					skCodeStream << "sk-code: " << wsUrlResult;
					ci_http_request_add_header(req, skCodeStream.str().c_str());
				}
			}
		}
		else if(
			su::isPrefixOfNoCase(cookieHeaderPrefix, header) ||
			su::isPrefixOfNoCase(hostHeaderPrefix, header)
		)
		{
			DLOG(1, "skipping header '" << header << "'");
		}
		else
		{
			// add all remaining headers
			ci_http_request_add_header(req, header.c_str());
		}
	}
	return CI_MOD_CONTINUE;
}

int safekiddo_end_of_data_handler(ci_request_t * req)
{
	return CI_MOD_DONE;
}

int safekiddo_io(char *wbuf, int *wlen, char *rbuf, int *rlen, int iseof, ci_request_t * req)
{
	int ret;
	struct body_data_t *body_data = (body_data_t*) ci_service_data(req);
	ret = CI_OK;

	 /*write the data read from icap_client to the echo_data->body*/
	 if(rlen && rbuf) {
		 *rlen = ci_ring_buf_write(body_data->body, rbuf, *rlen);
		 if (*rlen < 0)
		ret = CI_ERROR;
	 }

	 /*read some data from the echo_data->body and put them to the write buffer to be send
	  to the ICAP client*/
	 if (wbuf && wlen) {
		  *wlen = ci_ring_buf_read(body_data->body, wbuf, *wlen);
	 }
	 if(*wlen==0 && body_data->eof==1)
	 *wlen = CI_EOF;

	 return ret;
}

max_stars_repo_name: securesonic/safekiddo-backend

max_issues_repo_name: securesonic/safekiddo-backend

max_forks_repo_name: securesonic/safekiddo-backend


text: #include <boost/geometry/multi/algorithms/num_interior_rings.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino