<commit_before>#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/constants.hpp>
#include <mos/gfx/texture_2d.hpp>
#include <mos/gfx/camera.hpp>
#include <mos/gfx/target.hpp>

namespace mos {
namespace gfx {

/** Spotlight. */
class Light final {
public:
  explicit Light(const glm::vec3 &position = glm::vec3(0.0f, 0.0f, 2.0f),
                 const glm::vec3 &center = glm::vec3(0.0f, 0.0f, 0.0f),
                 const float angle = glm::half_pi<float>(),
                 const glm::vec3 &color = glm::vec3(0.0f),
                 const float strength = 100.0f,
                 const float near = 0.1f,
                 const float far = 100.0f);
  virtual ~Light();

  /** Set spot angle, in radans. */
  void angle(const float angle);

  float angle() const;

  /** Set position. */
  void position(const glm::vec3 &position);

  glm::vec3 position() const;

  /** Set center/focus point. */
  void center(const glm::vec3 &center);

  glm::vec3 center() const;

  glm::vec3 direction() const;

  glm::vec3 color;

  /** Strength of the lamp in watts. */
  float strength;

  /** Camera for shadow map rendering. */
  Camera camera;

private:
  float angle_;
  float near_;
  float far_;
};
}
}

<commit_msg>Change default<commit_after>#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/constants.hpp>
#include <mos/gfx/texture_2d.hpp>
#include <mos/gfx/camera.hpp>
#include <mos/gfx/target.hpp>

namespace mos {
namespace gfx {

/** Spotlight. */
class Light final {
public:
  explicit Light(const glm::vec3 &position = glm::vec3(0.0f, 0.0f, 2.0f),
                 const glm::vec3 &center = glm::vec3(0.0f, 0.0f, 0.0f),
                 const float angle = glm::half_pi<float>(),
                 const glm::vec3 &color = glm::vec3(0.0f),
                 const float strength = 100.0f,
                 const float near = 0.1f,
                 const float far = 10.0f);
  virtual ~Light();

  /** Set spot angle, in radans. */
  void angle(const float angle);

  float angle() const;

  /** Set position. */
  void position(const glm::vec3 &position);

  glm::vec3 position() const;

  /** Set center/focus point. */
  void center(const glm::vec3 &center);

  glm::vec3 center() const;

  glm::vec3 direction() const;

  glm::vec3 color;

  /** Strength of the lamp in watts. */
  float strength;

  /** Camera for shadow map rendering. */
  Camera camera;

private:
  float angle_;
  float near_;
  float far_;
};
}
}

<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

/**
 * @namespace nix::util
 * @brief Namespace for utility functions. This namespace is not part of the public API.
 */

#ifndef NIX_UTIL_H
#define NIX_UTIL_H

#include <nix/Exception.hpp>
#include <nix/Platform.hpp>

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

#include <boost/optional.hpp>
#include <boost/none_t.hpp>

namespace nix {

enum class DimensionType : unsigned int;

namespace util {

/**
 * @brief Remove blank spaces from the entire string
 *
 * @param str   The string to trim (will be modified in-place)
 */
NIXAPI void deblankString(std::string &str);

/**
 * @brief Remove blank spaces from the entire string
 *
 * @param str   The string to trim
 *
 * @return The trimmed string
 */
NIXAPI std::string deblankString(const std::string &str);

/**
 * @brief Replace forbidden chars in name string
 *
 * @param name   The string to sanitize
 *
 * @return The sanitized string
 */
NIXAPI std::string nameSanitizer(const std::string &name);

/**
 * @brief Check if the name is legit or needs the {@link nameSanitizer}
 *
 * @param name   The string to check
 *
 * @return true if name is legit, false otherwise
 */
NIXAPI bool nameCheck(const std::string &name);

/**
 * @brief Generates an ID-String.
 *
 * @return The generated id string.
 */
NIXAPI std::string createId();

/**
 * @brief Convert a time value into a string representation.
 *
 * @param time    The time to convert.
 *
 * @return The sting representation of time.
 */
NIXAPI std::string timeToStr(time_t time);

/**
 * @brief Convert a string representation of a date into a time value.
 *
 * @param time    The string representation of a date.
 *
 * @return The time value that is represented by the time parameter.
 */
NIXAPI time_t strToTime(const std::string &time);

/**
 * @brief Convert a time value into a string representation.
 *
 * @return The default time.
 */
NIXAPI time_t getTime();

/**
 * @brief Extract id from given entity. Does not work for dimensions
 *
 * @return The entity id.
 */
template<typename T>
std::string toId(const T &entity) {
    return entity.id();
}

/**
 * @brief Extract name from given entity. Does not work for dimensions
 *
 * @return The entity name.
 */
template<typename T>
std::string toName(const T &entity) {
    return entity.name();
}

/**
 * @brief Sanitizer function that deblanks units and replaces mu and µ
 * with the "u" replacement.
 *
 * @param unit The old unit.
 *
 * @return The sanitized unit.
 */
NIXAPI std::string unitSanitizer(const std::string &unit);

/**
 * @brief Checks if the passed string represents a valid SI unit.  The passed
 * unit may be atomic, e.g. 'V' or a compound unit, e.g. 'J/s'.
 *
 * @param unit  A string that is supposed to represent an SI unit.
 *
 * @return True if a valid SI unit, false otherwise.
 */
NIXAPI bool isSIUnit(const std::string &unit);

/**
 * @brief Checks if the passed string represents a valid SI unit.
 *
 * @param unit  A string that is supposed to represent an SI unit.
 *
 * @return True if a valid SI unit, false otherwise.
 */
NIXAPI bool isAtomicSIUnit(const std::string &unit);

/**
 * @brief Checks if the passed string is a valid combination of SI units.
 *
 * For example mV^2*Hz^-1. Method accepts only the * notation.
 *
 * @param unit  A string that should be tested
 *
 * @return True if a valid compound si unti, false otherwise.
 */
NIXAPI bool isCompoundSIUnit(const std::string &unit);

/**
 * @brief Returns whether or not two units represent scalable versions
 * of the same SI unit.
 *
 * @param unitA A string representing the first unit.
 *
 * @param unitB A string representing the second unit.
 *
 * @return True if the units are scalable version of the same unit.
 **/
NIXAPI bool isScalable(const std::string &unitA, const std::string &unitB);

/**
 * @brief Returns whether or not in all cases the units at the same
 * index in the two given unit vectors are scalable versions of the same
 * SI unit.
 *
 * @param unitsA A vector of unit strings.
 *
 * @param unitsB A vector of unit strings.
 *
 * @return True if the units are scalable version of the same unit.
 */
NIXAPI bool isScalable(const std::vector<std::string> &unitsA, const std::vector<std::string> &unitsB);

/**
 * @brief Returns whether or not in all cases the strings at the same
 * index in the two given string vectors are either both set or both
 * not set (empty).
 *
 * @param stringsA A vector of unit strings.
 *
 * @param stringsB A vector of unit strings.
 *
 * @return True if the units are scalable version of the same unit.
 */
NIXAPI bool isSetAtSamePos(const std::vector<std::string> &stringsA, const std::vector<std::string> &stringsB);

/**
 * @brief Get the scaling between two SI units that are identified by the two strings.
 *
 * @param originUnit            The original unit
 * @param destinationUnit       The one into which a scaling should be done
 *
 * @return A double with the appropriate scaling
 *
 * @throw std::runtime_error Exception when units cannot be converted into each other by mere scaling
 */
NIXAPI double getSIScaling(const std::string &originUnit, const std::string &destinationUnit);

/**
 * Splits an SI unit into prefix, unit and the power components.
 *
 * @param fullUnit
 * @param prefix
 * @param unit
 * @param power
 */
NIXAPI void splitUnit(const std::string &fullUnit, std::string &prefix, std::string &unit, std::string &power);

/**
 * Splits a SI unit compound into its atomic parts.
 *
 * @param compoundUnit  An SI unit that consists of many atomic units
 * @param atomicUnits   A vector that takes the atomic units
 */
NIXAPI void splitCompoundUnit(const std::string &compoundUnit, std::vector<std::string> &atomicUnits);

/**
 * @brief Converts minutes and hours to seconds.
 *
 * @param unit  The original unit (i.e. h for hour, or min for minutes)
 * @param value The original value
 *
 * @return The value in converted to seconds
*/
template<typename T>
T convertToSeconds(const std::string &unit, T value) {
    T seconds;
    if (unit == "min") {
        seconds = value * 60;
    } else if (unit == "h") {
        std::string new_unit = "min";
        seconds = convertToSeconds(new_unit, value * 60);
    } else if (unit == "s" || unit == "sec") {
        seconds = value;
    } else if (isScalable(unit, "s")) {
        double scaled = value * getSIScaling(unit, "s");
        seconds = static_cast<T>(std::is_integral<T>::value ? std::round(scaled) : scaled);
    } else {
        std::cerr <<  "[nix::util::convertToSeconds] Warning: given unit is not supported!" << std::endl;
        seconds = value;
    }
    return seconds;
}

/**
 * @brief Converts temperatures given in degrees Celsius of Fahrenheit to Kelvin.
 *
 * @param unit  The original unit {"F", "°F", "C", "°C"}
 * @param value The original value
 *
 * @return The temperature in Kelvin
 */
template<typename T>
T convertToKelvin(const std::string &unit, T value) {

   if (unit == "°K" || unit == "K") {
        return value; //nothing to do
   }

   double temperature;

   if (unit == "°C" || unit == "C") {
       temperature = value + 273.15;
   } else if (unit == "°F" || unit == "F") {
       temperature = (value - 32) * 5.0/9 + 273.15;
   } else if (unit == "°K" || unit == "K") {
       temperature = value;
   } else if (isScalable(unit, "K")) {
       temperature = value * getSIScaling(unit, "K");
   } else {
       std::cerr << "[nix::util::convertToKelvin] Warning: given unit is not supported" << std::endl;
       return value;
   }

   return static_cast<T>(std::is_integral<T>::value ? std::round(temperature) : temperature);
}

/**
 * @brief Convert a number into a string representation.
 *
 * @param number  The number to convert
 *
 * @return The string representation of number
 */
template<typename T>
std::string numToStr(T number) {
    std::stringstream s;
    s << number;
    return s.str();
}

/**
 * @brief Convert a DimensionType into a string representation.
 *
 * @param dtype  The DimensionType to convert
 *
 * @return The string representation of the DimensionType
 */
NIXAPI std::string dimTypeToStr(const DimensionType &dtype);

/**
 * @brief Convert string to number
 *
 * Convert a string representing a number into a number.
 *
 * @param str   The string to convert.
 *
 * @return The number that was represented by the string.
 */
template<typename T>
T strToNum(const std::string &str) {
    std::stringstream s(str);
    T number;
    return s >> number ? number : 0;
}

/*
 * Check whether a given type is of type "boost::optional"
 */
template<typename>
struct is_optional : std::false_type {};
template<typename T>
struct is_optional<boost::optional<T>> : std::true_type {};

/*
 * Optional de-referencing:
 * De-reference boost optional type if such given, returned var
 * unchanged otherwise.
 */
template<typename T>
T deRef(T var) {
    return var;
}
template<typename R>
R deRef(boost::optional<R> var) {
    if (var) return *var;
    else return R();
}

NIXAPI void applyPolynomial(const std::vector<double> &coefficients,
                            double origin,
                            const double *input,
                            double *output,
                            size_t n);

bool looksLikeUUID(const std::string &id);

} // namespace util
} // namespace nix

#endif // NIX_UTIL_H
<commit_msg>[util] cleanup of double-checking of a single case in convertToKelvin<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

/**
 * @namespace nix::util
 * @brief Namespace for utility functions. This namespace is not part of the public API.
 */

#ifndef NIX_UTIL_H
#define NIX_UTIL_H

#include <nix/Exception.hpp>
#include <nix/Platform.hpp>

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

#include <boost/optional.hpp>
#include <boost/none_t.hpp>

namespace nix {

enum class DimensionType : unsigned int;

namespace util {

/**
 * @brief Remove blank spaces from the entire string
 *
 * @param str   The string to trim (will be modified in-place)
 */
NIXAPI void deblankString(std::string &str);

/**
 * @brief Remove blank spaces from the entire string
 *
 * @param str   The string to trim
 *
 * @return The trimmed string
 */
NIXAPI std::string deblankString(const std::string &str);

/**
 * @brief Replace forbidden chars in name string
 *
 * @param name   The string to sanitize
 *
 * @return The sanitized string
 */
NIXAPI std::string nameSanitizer(const std::string &name);

/**
 * @brief Check if the name is legit or needs the {@link nameSanitizer}
 *
 * @param name   The string to check
 *
 * @return true if name is legit, false otherwise
 */
NIXAPI bool nameCheck(const std::string &name);

/**
 * @brief Generates an ID-String.
 *
 * @return The generated id string.
 */
NIXAPI std::string createId();

/**
 * @brief Convert a time value into a string representation.
 *
 * @param time    The time to convert.
 *
 * @return The sting representation of time.
 */
NIXAPI std::string timeToStr(time_t time);

/**
 * @brief Convert a string representation of a date into a time value.
 *
 * @param time    The string representation of a date.
 *
 * @return The time value that is represented by the time parameter.
 */
NIXAPI time_t strToTime(const std::string &time);

/**
 * @brief Convert a time value into a string representation.
 *
 * @return The default time.
 */
NIXAPI time_t getTime();

/**
 * @brief Extract id from given entity. Does not work for dimensions
 *
 * @return The entity id.
 */
template<typename T>
std::string toId(const T &entity) {
    return entity.id();
}

/**
 * @brief Extract name from given entity. Does not work for dimensions
 *
 * @return The entity name.
 */
template<typename T>
std::string toName(const T &entity) {
    return entity.name();
}

/**
 * @brief Sanitizer function that deblanks units and replaces mu and µ
 * with the "u" replacement.
 *
 * @param unit The old unit.
 *
 * @return The sanitized unit.
 */
NIXAPI std::string unitSanitizer(const std::string &unit);

/**
 * @brief Checks if the passed string represents a valid SI unit.  The passed
 * unit may be atomic, e.g. 'V' or a compound unit, e.g. 'J/s'.
 *
 * @param unit  A string that is supposed to represent an SI unit.
 *
 * @return True if a valid SI unit, false otherwise.
 */
NIXAPI bool isSIUnit(const std::string &unit);

/**
 * @brief Checks if the passed string represents a valid SI unit.
 *
 * @param unit  A string that is supposed to represent an SI unit.
 *
 * @return True if a valid SI unit, false otherwise.
 */
NIXAPI bool isAtomicSIUnit(const std::string &unit);

/**
 * @brief Checks if the passed string is a valid combination of SI units.
 *
 * For example mV^2*Hz^-1. Method accepts only the * notation.
 *
 * @param unit  A string that should be tested
 *
 * @return True if a valid compound si unti, false otherwise.
 */
NIXAPI bool isCompoundSIUnit(const std::string &unit);

/**
 * @brief Returns whether or not two units represent scalable versions
 * of the same SI unit.
 *
 * @param unitA A string representing the first unit.
 *
 * @param unitB A string representing the second unit.
 *
 * @return True if the units are scalable version of the same unit.
 **/
NIXAPI bool isScalable(const std::string &unitA, const std::string &unitB);

/**
 * @brief Returns whether or not in all cases the units at the same
 * index in the two given unit vectors are scalable versions of the same
 * SI unit.
 *
 * @param unitsA A vector of unit strings.
 *
 * @param unitsB A vector of unit strings.
 *
 * @return True if the units are scalable version of the same unit.
 */
NIXAPI bool isScalable(const std::vector<std::string> &unitsA, const std::vector<std::string> &unitsB);

/**
 * @brief Returns whether or not in all cases the strings at the same
 * index in the two given string vectors are either both set or both
 * not set (empty).
 *
 * @param stringsA A vector of unit strings.
 *
 * @param stringsB A vector of unit strings.
 *
 * @return True if the units are scalable version of the same unit.
 */
NIXAPI bool isSetAtSamePos(const std::vector<std::string> &stringsA, const std::vector<std::string> &stringsB);

/**
 * @brief Get the scaling between two SI units that are identified by the two strings.
 *
 * @param originUnit            The original unit
 * @param destinationUnit       The one into which a scaling should be done
 *
 * @return A double with the appropriate scaling
 *
 * @throw std::runtime_error Exception when units cannot be converted into each other by mere scaling
 */
NIXAPI double getSIScaling(const std::string &originUnit, const std::string &destinationUnit);

/**
 * Splits an SI unit into prefix, unit and the power components.
 *
 * @param fullUnit
 * @param prefix
 * @param unit
 * @param power
 */
NIXAPI void splitUnit(const std::string &fullUnit, std::string &prefix, std::string &unit, std::string &power);

/**
 * Splits a SI unit compound into its atomic parts.
 *
 * @param compoundUnit  An SI unit that consists of many atomic units
 * @param atomicUnits   A vector that takes the atomic units
 */
NIXAPI void splitCompoundUnit(const std::string &compoundUnit, std::vector<std::string> &atomicUnits);

/**
 * @brief Converts minutes and hours to seconds.
 *
 * @param unit  The original unit (i.e. h for hour, or min for minutes)
 * @param value The original value
 *
 * @return The value in converted to seconds
*/
template<typename T>
T convertToSeconds(const std::string &unit, T value) {
    T seconds;
    if (unit == "min") {
        seconds = value * 60;
    } else if (unit == "h") {
        std::string new_unit = "min";
        seconds = convertToSeconds(new_unit, value * 60);
    } else if (unit == "s" || unit == "sec") {
        seconds = value;
    } else if (isScalable(unit, "s")) {
        double scaled = value * getSIScaling(unit, "s");
        seconds = static_cast<T>(std::is_integral<T>::value ? std::round(scaled) : scaled);
    } else {
        std::cerr <<  "[nix::util::convertToSeconds] Warning: given unit is not supported!" << std::endl;
        seconds = value;
    }
    return seconds;
}

/**
 * @brief Converts temperatures given in degrees Celsius of Fahrenheit to Kelvin.
 *
 * @param unit  The original unit {"F", "°F", "C", "°C"}
 * @param value The original value
 *
 * @return The temperature in Kelvin
 */
template<typename T>
T convertToKelvin(const std::string &unit, T value) {

   if (unit == "°K" || unit == "K") {
       return value;
   }

   double temperature;
   if (unit == "°C" || unit == "C") {
       temperature = value + 273.15;
   } else if (unit == "°F" || unit == "F") {
       temperature = (value - 32) * 5.0/9 + 273.15;
   } else if (isScalable(unit, "K")) {
       temperature = value * getSIScaling(unit, "K");
   } else {
       std::cerr << "[nix::util::convertToKelvin] Warning: given unit is not supported" << std::endl;
       return value;
   }

   return static_cast<T>(std::is_integral<T>::value ? std::round(temperature) : temperature);
}

/**
 * @brief Convert a number into a string representation.
 *
 * @param number  The number to convert
 *
 * @return The string representation of number
 */
template<typename T>
std::string numToStr(T number) {
    std::stringstream s;
    s << number;
    return s.str();
}

/**
 * @brief Convert a DimensionType into a string representation.
 *
 * @param dtype  The DimensionType to convert
 *
 * @return The string representation of the DimensionType
 */
NIXAPI std::string dimTypeToStr(const DimensionType &dtype);

/**
 * @brief Convert string to number
 *
 * Convert a string representing a number into a number.
 *
 * @param str   The string to convert.
 *
 * @return The number that was represented by the string.
 */
template<typename T>
T strToNum(const std::string &str) {
    std::stringstream s(str);
    T number;
    return s >> number ? number : 0;
}

/*
 * Check whether a given type is of type "boost::optional"
 */
template<typename>
struct is_optional : std::false_type {};
template<typename T>
struct is_optional<boost::optional<T>> : std::true_type {};

/*
 * Optional de-referencing:
 * De-reference boost optional type if such given, returned var
 * unchanged otherwise.
 */
template<typename T>
T deRef(T var) {
    return var;
}
template<typename R>
R deRef(boost::optional<R> var) {
    if (var) return *var;
    else return R();
}

NIXAPI void applyPolynomial(const std::vector<double> &coefficients,
                            double origin,
                            const double *input,
                            double *output,
                            size_t n);

bool looksLikeUUID(const std::string &id);

} // namespace util
} // namespace nix

#endif // NIX_UTIL_H
<|endoftext|>


<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/listbox.hpp"

#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"
#include "guichan/selectionlistener.hpp"

namespace gcn
{
    ListBox::ListBox()
        : mSelected(-1),
          mListModel(NULL),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    ListBox::ListBox(ListModel *listModel)
        : mSelected(-1),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setListModel(listModel);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    void ListBox::draw(Graphics* graphics)
    {
        graphics->setColor(getBackgroundColor());
        graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));

        if (mListModel == NULL)
        {
            return;
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());

        // Check the current clip area so we don't draw unnecessary items
        // that are not visible.
        const ClipRectangle currentClipArea = graphics->getCurrentClipArea();
        int fontHeight = getFont()->getHeight();
        int i = currentClipArea.y / getFont()->getHeight();
        int end = (currentClipArea.y + currentClipArea.height) / getFont()->getHeight();
        int y = 0;

        for (i = 0; i < end; ++i)
        {
            if (i == mSelected)
            {
                graphics->setColor(getSelectionColor());
                graphics->fillRectangle(Rectangle(0, y, getWidth(), fontHeight));
                graphics->setColor(getForegroundColor());
            }

            graphics->drawText(mListModel->getElementAt(i), 1, y);

            y += fontHeight;
        }
    }

    void ListBox::logic()
    {
        adjustSize();
    }

    int ListBox::getSelected() const
    {
        return mSelected;
    }

    void ListBox::setSelected(int selected)
    {
        if (mListModel == NULL)
        {
            mSelected = -1;
        }
        else
        {
            if (selected < 0)
            {
                mSelected = -1;
            }
            else if (selected >= mListModel->getNumberOfElements())
            {
                mSelected = mListModel->getNumberOfElements() - 1;
            }
            else
            {
                mSelected = selected;
            }

            Widget *par = getParent();
            if (par == NULL)
            {
                return;
            }

            Rectangle scroll;

            if (mSelected < 0)
            {
                scroll.y = 0;
            }
            else
            {
                scroll.y = getFont()->getHeight() * mSelected;
            }

            scroll.height = getFont()->getHeight();
            par->showWidgetPart(this, scroll);
        }

        distributeValueChangedEvent();
    }

    void ListBox::keyPressed(KeyEvent& keyEvent)
    {
        Key key = keyEvent.getKey();

        if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
        {
            distributeActionEvent();
            keyEvent.consume();
        }
        else if (key.getValue() == Key::UP)
        {
            setSelected(mSelected - 1);

            if (mSelected == -1)
            {
                if (mWrappingEnabled)
                {
                    setSelected(getListModel()->getNumberOfElements() - 1);
                }
                else
                {
                    setSelected(0);
                }
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::DOWN)
        {
            if (mWrappingEnabled
                && getSelected() == getListModel()->getNumberOfElements() - 1)
            {
                setSelected(0);
            }
            else
            {
                setSelected(getSelected() + 1);
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::HOME)
        {
            setSelected(0);
            keyEvent.consume();
        }
        else if (key.getValue() == Key::END)
        {
            setSelected(getListModel()->getNumberOfElements() - 1);
            keyEvent.consume();
        }
    }

    void ListBox::mousePressed(MouseEvent& mouseEvent)
    {
        if (mouseEvent.getButton() == MouseEvent::LEFT)
        {
            setSelected(mouseEvent.getY() / getFont()->getHeight());
            distributeActionEvent();
        }
    }

    void ListBox::mouseWheelMovedUp(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            if (getSelected() > 0 )
            {
                setSelected(getSelected() - 1);
            }

            mouseEvent.consume();
        }
    }

    void ListBox::mouseWheelMovedDown(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            setSelected(getSelected() + 1);

            mouseEvent.consume();
        }
    }

    void ListBox::mouseDragged(MouseEvent& mouseEvent)
    {
        mouseEvent.consume();
    }

    void ListBox::setListModel(ListModel *listModel)
    {
        mSelected = -1;
        mListModel = listModel;
        adjustSize();
    }

    ListModel* ListBox::getListModel()
    {
        return mListModel;
    }

    void ListBox::adjustSize()
    {
        if (mListModel != NULL)
        {
            setHeight(getFont()->getHeight() * mListModel->getNumberOfElements());
        }
    }

    bool ListBox::isWrappingEnabled() const
    {
        return mWrappingEnabled;
    }

    void ListBox::setWrappingEnabled(bool wrappingEnabled)
    {
        mWrappingEnabled = wrappingEnabled;
    }

    void ListBox::addSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.push_back(selectionListener);
    }

    void ListBox::removeSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.remove(selectionListener);
    }

    void ListBox::distributeValueChangedEvent()
    {
        SelectionListenerIterator iter;

        for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter)
        {
            SelectionEvent event(this);
            (*iter)->valueChanged(event);
        }
    }
}
<commit_msg>Bug fix in list box has been applied where list box might have tried to retrieve an item outside of the index range of the list model.<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/listbox.hpp"

#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"
#include "guichan/selectionlistener.hpp"

namespace gcn
{
    ListBox::ListBox()
        : mSelected(-1),
          mListModel(NULL),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    ListBox::ListBox(ListModel *listModel)
        : mSelected(-1),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setListModel(listModel);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    void ListBox::draw(Graphics* graphics)
    {
        graphics->setColor(getBackgroundColor());
        graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));

        if (mListModel == NULL)
        {
            return;
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());

        // Check the current clip area so we don't draw unnecessary items
        // that are not visible.
        const ClipRectangle currentClipArea = graphics->getCurrentClipArea();
        int fontHeight = getFont()->getHeight();
        int i = currentClipArea.y / getFont()->getHeight();
        int end = (currentClipArea.y + currentClipArea.height) / getFont()->getHeight();

        if (end >= mListModel->getNumberOfElements())
        {
            end = mListModel->getNumberOfElements() - 1;
        }

        int y = 0;

        for (i = 0; i < end; ++i)
        {
            if (i == mSelected)
            {
                graphics->setColor(getSelectionColor());
                graphics->fillRectangle(Rectangle(0, y, getWidth(), fontHeight));
                graphics->setColor(getForegroundColor());
            }

            graphics->drawText(mListModel->getElementAt(i), 1, y);

            y += fontHeight;
        }
    }

    void ListBox::logic()
    {
        adjustSize();
    }

    int ListBox::getSelected() const
    {
        return mSelected;
    }

    void ListBox::setSelected(int selected)
    {
        if (mListModel == NULL)
        {
            mSelected = -1;
        }
        else
        {
            if (selected < 0)
            {
                mSelected = -1;
            }
            else if (selected >= mListModel->getNumberOfElements())
            {
                mSelected = mListModel->getNumberOfElements() - 1;
            }
            else
            {
                mSelected = selected;
            }

            Widget *par = getParent();
            if (par == NULL)
            {
                return;
            }

            Rectangle scroll;

            if (mSelected < 0)
            {
                scroll.y = 0;
            }
            else
            {
                scroll.y = getFont()->getHeight() * mSelected;
            }

            scroll.height = getFont()->getHeight();
            par->showWidgetPart(this, scroll);
        }

        distributeValueChangedEvent();
    }

    void ListBox::keyPressed(KeyEvent& keyEvent)
    {
        Key key = keyEvent.getKey();

        if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
        {
            distributeActionEvent();
            keyEvent.consume();
        }
        else if (key.getValue() == Key::UP)
        {
            setSelected(mSelected - 1);

            if (mSelected == -1)
            {
                if (mWrappingEnabled)
                {
                    setSelected(getListModel()->getNumberOfElements() - 1);
                }
                else
                {
                    setSelected(0);
                }
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::DOWN)
        {
            if (mWrappingEnabled
                && getSelected() == getListModel()->getNumberOfElements() - 1)
            {
                setSelected(0);
            }
            else
            {
                setSelected(getSelected() + 1);
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::HOME)
        {
            setSelected(0);
            keyEvent.consume();
        }
        else if (key.getValue() == Key::END)
        {
            setSelected(getListModel()->getNumberOfElements() - 1);
            keyEvent.consume();
        }
    }

    void ListBox::mousePressed(MouseEvent& mouseEvent)
    {
        if (mouseEvent.getButton() == MouseEvent::LEFT)
        {
            setSelected(mouseEvent.getY() / getFont()->getHeight());
            distributeActionEvent();
        }
    }

    void ListBox::mouseWheelMovedUp(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            if (getSelected() > 0 )
            {
                setSelected(getSelected() - 1);
            }

            mouseEvent.consume();
        }
    }

    void ListBox::mouseWheelMovedDown(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            setSelected(getSelected() + 1);

            mouseEvent.consume();
        }
    }

    void ListBox::mouseDragged(MouseEvent& mouseEvent)
    {
        mouseEvent.consume();
    }

    void ListBox::setListModel(ListModel *listModel)
    {
        mSelected = -1;
        mListModel = listModel;
        adjustSize();
    }

    ListModel* ListBox::getListModel()
    {
        return mListModel;
    }

    void ListBox::adjustSize()
    {
        if (mListModel != NULL)
        {
            setHeight(getFont()->getHeight() * mListModel->getNumberOfElements());
        }
    }

    bool ListBox::isWrappingEnabled() const
    {
        return mWrappingEnabled;
    }

    void ListBox::setWrappingEnabled(bool wrappingEnabled)
    {
        mWrappingEnabled = wrappingEnabled;
    }

    void ListBox::addSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.push_back(selectionListener);
    }

    void ListBox::removeSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.remove(selectionListener);
    }

    void ListBox::distributeValueChangedEvent()
    {
        SelectionListenerIterator iter;

        for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter)
        {
            SelectionEvent event(this);
            (*iter)->valueChanged(event);
        }
    }
}
<|endoftext|>


<commit_before>#include "listbox.h"
#include "../core/color.h"
#include "../core/utility.h"
#include <iostream>

void ListBox::render()
{
    for (unsigned int ii = 0; ii < this->getHeight(); ii++) {
        if (ii >= items.size()) {
            break;
        }
        if (m_selectedItem-m_topOffset == ii) {
            this->drawString(0, ii, ">", COLOR(RED));
        }

        this->drawString(1, ii, items[ii+m_topOffset].c_str());
    }
}

void ListBox::keyPress(unsigned char key)
{
    if (key == '+') {
        m_selectedItem = (m_selectedItem == items.size()-1) ? items.size()-1: m_selectedItem+1;
        if (m_selectedItem >= this->getHeight()) {
            m_topOffset = m_selectedItem - this->getHeight() + 1;
        }
    }
    if (key == '-') {
        m_selectedItem = (m_selectedItem == 0) ? 0 : m_selectedItem-1;
        if (m_selectedItem < m_topOffset) {
            m_topOffset = 0;
        }
    }
    if (key == KEY_ENTER && onItemSelected) {
        onItemSelected(this);
    }
}
<commit_msg>Added alternative selection keys to listbox<commit_after>#include "listbox.h"
#include "../core/color.h"
#include "../core/utility.h"
#include <iostream>

void ListBox::render()
{
    for (unsigned int ii = 0; ii < this->getHeight(); ii++) {
        if (ii >= items.size()) {
            break;
        }
        if (m_selectedItem-m_topOffset == ii) {
            this->drawString(0, ii, ">", COLOR(RED));
        }

        this->drawString(1, ii, items[ii+m_topOffset].c_str());
    }
}

void ListBox::keyPress(unsigned char key)
{
    if (key == '+' || key == KEY_DOWN) {
        m_selectedItem = (m_selectedItem == items.size()-1) ? items.size()-1: m_selectedItem+1;
        if (m_selectedItem >= this->getHeight()) {
            m_topOffset = m_selectedItem - this->getHeight() + 1;
        }
    }
    if (key == '-' || key == KEY_UP) {
        m_selectedItem = (m_selectedItem == 0) ? 0 : m_selectedItem-1;
        if (m_selectedItem < m_topOffset) {
            m_topOffset = 0;
        }
    }
    if (key == KEY_ENTER && onItemSelected) {
        onItemSelected(this);
    }
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee Modules --- XRule Exception
 *
 * @author Sam Baskinger <sbaskinger@qualys.com>
 */

#include "xrules.hpp"
#include "xrules_acls.hpp"
#include "xrules_exception.hpp"

#include <strings.h>

#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>

namespace {

/**
 * Utility function to parse an argument for XRuleException configurations.
 *
 * This takes an XRuleException argument, checks the provided prefix,
 * and if it matches returns IB_OK and assigns the `char *` following the
 * prefix in @a arg to @a rest. Thus, the caller is provided with
 * the value following the prefix and may continue parsing it.
 *
 * @param[in] expected The expected value. A case insensitive comparison
 *            is done between @a expected and @a arg.
 * @param[in] arg The argument to check.
 * @param[in] rest The rest of @a arg following the prefix @a exected.
 *
 * @returns
 * - IB_OK On success and a match.
 * - IB_ENOENT If @a expected does not match @a arg.
 */
ib_status_t parse_arg(
    const char  *expected,
    const char  *arg,
    const char **rest
)
{
    size_t len = strlen(expected);
    if (strncasecmp(expected, arg, len) == 0) {
        (*rest) = arg+len;
        return IB_OK;
    }
    else {
        return IB_ENOENT;
    }
}

/**
 * Use ib_uuid_create_v4() to generate a name.
 *
 * This is used to name Actions when the name is not important.
 */
std::string random_name()
{
    std::vector<char> uuid(IB_UUID_LENGTH);

    IronBee::throw_if_error(ib_uuid_create_v4(&(uuid[0])));

    return std::string(&(uuid[0]));
}

/**
 * A ConclusionAction is an action that conditionally fires when it is applied.
 *
 * To implement an XRuleException we actually wire together many
 * FactActions which, after each is called, attempts to apply the
 * ConclusionAction.
 *
 * The ConclusionAction will only fire if all its facts are true (results=1).
 */
class ConclusionAction : public Action
{
public:
    /**
     * Construct a conclusion action that depends on @a results.
     *
     * @param[in] action The user's action to execute when all FactAction s
     *            are true.
     * @param[in] results The number of results this ConclusionAction should
     *            create to be given to FactActions.
     */
    ConclusionAction(action_ptr action, int results);

    /**
     * Return a reference to the boolean that denotes a particular result.
     *
     * @param[in] mdata Module data.
     * @param[in] i The index of the result to fetch. This must be in
     * the range 0 through the number of results specified when this
     * object was created.
     *
     * @returns The int refernce to assign to.
     */
    int& result(
        XRulesModuleTxData& mdata,
        int i
    );

private:
    //! The action that is applied if all results are true.
    action_ptr m_action;

    /**
     * A vector of results (0=failed/not executed, 1=success).
     *
     * Only when all of these are equal to 1 will ConclusionAction::m_action
     * be executed.
     */
    size_t m_results;

    /**
     * Apply this action to the transaction if all results are non-zero.
     *
     * @param[in] mdata The module.
     * @param[in] tx The current transaction.
     */
    virtual void apply_impl(
        xrules_module_tx_data_ptr mdata,
        IronBee::Transaction      tx
    ) const;
};

ConclusionAction::ConclusionAction(action_ptr action, int results):
    Action(random_name(), 10),
    m_action(action),
    m_results(results)
{}

int& ConclusionAction::result(
    XRulesModuleTxData& mdata,
    int i
)
{
    std::vector<int>& v = mdata.exception_facts[this];

    if (v.size() <= m_results) {
        v.resize(m_results);
    }

    return v[i];
}

void ConclusionAction::apply_impl(
    xrules_module_tx_data_ptr mdata,
    IronBee::Transaction      tx
) const
{
    std::vector<int>& v = (*mdata).exception_facts[this];

    BOOST_FOREACH(int r, v) {
        if (r != 1) {
            return;
        }
    }

    /* If we reach this code, all results were = 1. Execute. */
    (*m_action)(mdata, tx);
}

/**
 * This action initializes facts to false (0) and sets them to true (1).
 *
 * To implement an XRuleException we must collect various facts, such as
 * is a Path equal to some prefix, is a source IP in a subnet, etc.
 * To collect these facts XRules are created and given FactActions
 * which record that a given XRule was true and fired its action.
 *
 * When any FactAction fires, as its last action, it calls its
 * associated ConclusionAction. A ConclusionAction will check if all
 * FactActions have set their facts to true (1). Only if all facts are
 * true does the ConclusionAction then fire its own associated Action.
 * The ConclusionAction's Action is the action the user requested
 * in the configuration language.
 */
class FactAction : public Action
{
public:

    /**
     * Construct a new action.
     *
     * @param[in] conclusion The conclusion action that this Fact is
     *            gateing the execution of.
     * @param[in] result_idx The index of the result in the result
     *            vector of the ConclusionAction.
     *
     * @note This takes a reference to a boolean because actions may
     *       not modify themselves.
     */
    FactAction(action_ptr conclusion, int result_idx);

private:
    action_ptr  m_conclusion;
    int         m_result_idx;

    /**
     * Apply this action to the transaction.
     *
     * @param[in] mdata The module.
     * @param[in] tx The current transaction.
     */
    virtual void apply_impl(
        xrules_module_tx_data_ptr mdata,
        IronBee::Transaction      tx
    ) const;
};

FactAction::FactAction(action_ptr conclusion, int result_idx) :
    Action(random_name(), 10),
    m_conclusion(conclusion),
    m_result_idx(result_idx)
{}

void FactAction::apply_impl(
    xrules_module_tx_data_ptr mdata,
    IronBee::Transaction      tx
) const
{

    /* Update the results. */
    static_cast<ConclusionAction&>(*m_conclusion).result(*mdata, m_result_idx) = 1;

    /* Having updated the results, try the conclusion. */
    (*m_conclusion)(mdata, tx);
}

} /* Anonymous Namespace */

void XRuleException::xrule_directive(
    XRulesModule                     module,
    IronBee::ConfigurationParser     cp,
    const char *                     name,
    IronBee::ConstList<const char *> all_params
)
{
    IronBee::Context    ctx = cp.current_context();
    XRulesModuleConfig& cfg =
        module.module().configuration_data<XRulesModuleConfig>(ctx);

    /* The unparsed bits from parsing an action out of the params arg. */
    IronBee::List<const char *> params =
        IronBee::List<const char *>::create(cp.memory_manager());

    /* Parse the action and put the remaining tokens in `params`. */
    action_ptr user_action = module.parse_action(cp, all_params, params);

    /* Construct a conclusion action that will fire the user's action. */
    action_ptr conclusion(
        boost::make_shared<ConclusionAction>(
            user_action,
            params.size()));

    if (params.empty()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval()
                << IronBee::errinfo_what(
                    "XRuleException require at least 1 argument.")
        );
    }

    int result_idx = 0;
    BOOST_FOREACH(const char* param, params) {
        const char* val;

        /* Build a new FactAction to
         * - Set the result `result_idx` to 1.
         * - Fire the conclusion action. */
        action_ptr action(
            boost::make_shared<FactAction>(
                conclusion,
                result_idx));

        ++result_idx;

        if (IB_OK == parse_arg("EventTag:", param, &val)) {
            IronBee::List<const char *> l =
                IronBee::List<const char *>::create(cp.memory_manager());
            l.push_back(val);
            cfg.event_xrules.push_back(
                xrule_ptr(
                    new XRuleEventTag(l, action)));
        }
        else if (IB_OK == parse_arg("IPv4:", param, &val)) {
            // Copy in an empty, uninitialized ipset entry.
            ib_ipset4_entry_t entry;

            memset(&entry, 0, sizeof(entry));

            val = XRuleIP::normalize_ipv4(cp.memory_manager(), val);

            IronBee::throw_if_error(
                ib_ip4_str_to_net(val, &(entry.network)),
                (std::string("Failed to get net from string: ")+val).c_str()
            );

            // Put that action in the ip set.
            entry.data = IronBee::value_to_data<action_ptr>(
                action,
                cp.engine().main_memory_mm().ib());

            cfg.ipv4_list.push_back(entry);
        }
        else if (IB_OK == parse_arg("IPv6:", param, &val)) {
            // Copy in an empty, uninitialized ipset entry.
            ib_ipset6_entry_t entry;

            memset(&entry, 0, sizeof(entry));

            val = XRuleIP::normalize_ipv6(cp.memory_manager(), val);

            IronBee::throw_if_error(
                ib_ip6_str_to_net(val, &(entry.network)),
                (std::string("Failed to get net from string: ")+val).c_str()
            );

            // Put that action in the ip set.
            entry.data = IronBee::value_to_data<action_ptr>(
                action,
                cp.engine().main_memory_mm().ib());

            cfg.ipv6_list.push_back(entry);
        }
        else if (IB_OK == parse_arg("Geo:", param, &val)) {
            cfg.req_xrules.push_back(
                xrule_ptr(
                    new XRuleGeo(val, action)));
        }
        else if (IB_OK == parse_arg("Path:", param, &val)) {
            cfg.req_xrules.push_back(
                xrule_ptr(
                    new XRulePath(val, action)));
        } else {
            BOOST_THROW_EXCEPTION(
                IronBee::enoent()
                    << IronBee::errinfo_what(
                        std::string("Unknown XRuleException: ")+param)
            );
        }
    }
}
<commit_msg>modules/xrules_exception.cpp: Uncradle else.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief IronBee Modules --- XRule Exception
 *
 * @author Sam Baskinger <sbaskinger@qualys.com>
 */

#include "xrules.hpp"
#include "xrules_acls.hpp"
#include "xrules_exception.hpp"

#include <strings.h>

#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>

namespace {

/**
 * Utility function to parse an argument for XRuleException configurations.
 *
 * This takes an XRuleException argument, checks the provided prefix,
 * and if it matches returns IB_OK and assigns the `char *` following the
 * prefix in @a arg to @a rest. Thus, the caller is provided with
 * the value following the prefix and may continue parsing it.
 *
 * @param[in] expected The expected value. A case insensitive comparison
 *            is done between @a expected and @a arg.
 * @param[in] arg The argument to check.
 * @param[in] rest The rest of @a arg following the prefix @a exected.
 *
 * @returns
 * - IB_OK On success and a match.
 * - IB_ENOENT If @a expected does not match @a arg.
 */
ib_status_t parse_arg(
    const char  *expected,
    const char  *arg,
    const char **rest
)
{
    size_t len = strlen(expected);
    if (strncasecmp(expected, arg, len) == 0) {
        (*rest) = arg+len;
        return IB_OK;
    }
    else {
        return IB_ENOENT;
    }
}

/**
 * Use ib_uuid_create_v4() to generate a name.
 *
 * This is used to name Actions when the name is not important.
 */
std::string random_name()
{
    std::vector<char> uuid(IB_UUID_LENGTH);

    IronBee::throw_if_error(ib_uuid_create_v4(&(uuid[0])));

    return std::string(&(uuid[0]));
}

/**
 * A ConclusionAction is an action that conditionally fires when it is applied.
 *
 * To implement an XRuleException we actually wire together many
 * FactActions which, after each is called, attempts to apply the
 * ConclusionAction.
 *
 * The ConclusionAction will only fire if all its facts are true (results=1).
 */
class ConclusionAction : public Action
{
public:
    /**
     * Construct a conclusion action that depends on @a results.
     *
     * @param[in] action The user's action to execute when all FactAction s
     *            are true.
     * @param[in] results The number of results this ConclusionAction should
     *            create to be given to FactActions.
     */
    ConclusionAction(action_ptr action, int results);

    /**
     * Return a reference to the boolean that denotes a particular result.
     *
     * @param[in] mdata Module data.
     * @param[in] i The index of the result to fetch. This must be in
     * the range 0 through the number of results specified when this
     * object was created.
     *
     * @returns The int refernce to assign to.
     */
    int& result(
        XRulesModuleTxData& mdata,
        int i
    );

private:
    //! The action that is applied if all results are true.
    action_ptr m_action;

    /**
     * A vector of results (0=failed/not executed, 1=success).
     *
     * Only when all of these are equal to 1 will ConclusionAction::m_action
     * be executed.
     */
    size_t m_results;

    /**
     * Apply this action to the transaction if all results are non-zero.
     *
     * @param[in] mdata The module.
     * @param[in] tx The current transaction.
     */
    virtual void apply_impl(
        xrules_module_tx_data_ptr mdata,
        IronBee::Transaction      tx
    ) const;
};

ConclusionAction::ConclusionAction(action_ptr action, int results):
    Action(random_name(), 10),
    m_action(action),
    m_results(results)
{}

int& ConclusionAction::result(
    XRulesModuleTxData& mdata,
    int i
)
{
    std::vector<int>& v = mdata.exception_facts[this];

    if (v.size() <= m_results) {
        v.resize(m_results);
    }

    return v[i];
}

void ConclusionAction::apply_impl(
    xrules_module_tx_data_ptr mdata,
    IronBee::Transaction      tx
) const
{
    std::vector<int>& v = (*mdata).exception_facts[this];

    BOOST_FOREACH(int r, v) {
        if (r != 1) {
            return;
        }
    }

    /* If we reach this code, all results were = 1. Execute. */
    (*m_action)(mdata, tx);
}

/**
 * This action initializes facts to false (0) and sets them to true (1).
 *
 * To implement an XRuleException we must collect various facts, such as
 * is a Path equal to some prefix, is a source IP in a subnet, etc.
 * To collect these facts XRules are created and given FactActions
 * which record that a given XRule was true and fired its action.
 *
 * When any FactAction fires, as its last action, it calls its
 * associated ConclusionAction. A ConclusionAction will check if all
 * FactActions have set their facts to true (1). Only if all facts are
 * true does the ConclusionAction then fire its own associated Action.
 * The ConclusionAction's Action is the action the user requested
 * in the configuration language.
 */
class FactAction : public Action
{
public:

    /**
     * Construct a new action.
     *
     * @param[in] conclusion The conclusion action that this Fact is
     *            gateing the execution of.
     * @param[in] result_idx The index of the result in the result
     *            vector of the ConclusionAction.
     *
     * @note This takes a reference to a boolean because actions may
     *       not modify themselves.
     */
    FactAction(action_ptr conclusion, int result_idx);

private:
    action_ptr  m_conclusion;
    int         m_result_idx;

    /**
     * Apply this action to the transaction.
     *
     * @param[in] mdata The module.
     * @param[in] tx The current transaction.
     */
    virtual void apply_impl(
        xrules_module_tx_data_ptr mdata,
        IronBee::Transaction      tx
    ) const;
};

FactAction::FactAction(action_ptr conclusion, int result_idx) :
    Action(random_name(), 10),
    m_conclusion(conclusion),
    m_result_idx(result_idx)
{}

void FactAction::apply_impl(
    xrules_module_tx_data_ptr mdata,
    IronBee::Transaction      tx
) const
{

    /* Update the results. */
    static_cast<ConclusionAction&>(*m_conclusion).result(*mdata, m_result_idx) = 1;

    /* Having updated the results, try the conclusion. */
    (*m_conclusion)(mdata, tx);
}

} /* Anonymous Namespace */

void XRuleException::xrule_directive(
    XRulesModule                     module,
    IronBee::ConfigurationParser     cp,
    const char *                     name,
    IronBee::ConstList<const char *> all_params
)
{
    IronBee::Context    ctx = cp.current_context();
    XRulesModuleConfig& cfg =
        module.module().configuration_data<XRulesModuleConfig>(ctx);

    /* The unparsed bits from parsing an action out of the params arg. */
    IronBee::List<const char *> params =
        IronBee::List<const char *>::create(cp.memory_manager());

    /* Parse the action and put the remaining tokens in `params`. */
    action_ptr user_action = module.parse_action(cp, all_params, params);

    /* Construct a conclusion action that will fire the user's action. */
    action_ptr conclusion(
        boost::make_shared<ConclusionAction>(
            user_action,
            params.size()));

    if (params.empty()) {
        BOOST_THROW_EXCEPTION(
            IronBee::einval()
                << IronBee::errinfo_what(
                    "XRuleException require at least 1 argument.")
        );
    }

    int result_idx = 0;
    BOOST_FOREACH(const char* param, params) {
        const char* val;

        /* Build a new FactAction to
         * - Set the result `result_idx` to 1.
         * - Fire the conclusion action. */
        action_ptr action(
            boost::make_shared<FactAction>(
                conclusion,
                result_idx));

        ++result_idx;

        if (IB_OK == parse_arg("EventTag:", param, &val)) {
            IronBee::List<const char *> l =
                IronBee::List<const char *>::create(cp.memory_manager());
            l.push_back(val);
            cfg.event_xrules.push_back(
                xrule_ptr(
                    new XRuleEventTag(l, action)));
        }
        else if (IB_OK == parse_arg("IPv4:", param, &val)) {
            // Copy in an empty, uninitialized ipset entry.
            ib_ipset4_entry_t entry;

            memset(&entry, 0, sizeof(entry));

            val = XRuleIP::normalize_ipv4(cp.memory_manager(), val);

            IronBee::throw_if_error(
                ib_ip4_str_to_net(val, &(entry.network)),
                (std::string("Failed to get net from string: ")+val).c_str()
            );

            // Put that action in the ip set.
            entry.data = IronBee::value_to_data<action_ptr>(
                action,
                cp.engine().main_memory_mm().ib());

            cfg.ipv4_list.push_back(entry);
        }
        else if (IB_OK == parse_arg("IPv6:", param, &val)) {
            // Copy in an empty, uninitialized ipset entry.
            ib_ipset6_entry_t entry;

            memset(&entry, 0, sizeof(entry));

            val = XRuleIP::normalize_ipv6(cp.memory_manager(), val);

            IronBee::throw_if_error(
                ib_ip6_str_to_net(val, &(entry.network)),
                (std::string("Failed to get net from string: ")+val).c_str()
            );

            // Put that action in the ip set.
            entry.data = IronBee::value_to_data<action_ptr>(
                action,
                cp.engine().main_memory_mm().ib());

            cfg.ipv6_list.push_back(entry);
        }
        else if (IB_OK == parse_arg("Geo:", param, &val)) {
            cfg.req_xrules.push_back(
                xrule_ptr(
                    new XRuleGeo(val, action)));
        }
        else if (IB_OK == parse_arg("Path:", param, &val)) {
            cfg.req_xrules.push_back(
                xrule_ptr(
                    new XRulePath(val, action)));
        }
        else {
            BOOST_THROW_EXCEPTION(
                IronBee::enoent()
                    << IronBee::errinfo_what(
                        std::string("Unknown XRuleException: ")+param)
            );
        }
    }
}
<|endoftext|>


<commit_before>#include <pcl/point_cloud.h>
#include <pcl_ros/point_cloud.h>
#include <ros/publisher.h>
#include <ros/ros.h>
#include <stdlib.h>
#include <Eigen/Core>
#include <opencv2/opencv.hpp>
#include <opencv2/core/eigen.hpp>
#include <pcl_ros/transforms.h>
#include <igvc_msgs/velocity_pair.h>
#include <igvc_msgs/map.h>
#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>

igvc_msgs::map msgBoi;
cv_bridge::CvImage img_bridge;
sensor_msgs::Image imageBoi; // >> message to be sent

ros::Publisher map_pub;
cv::Mat* published_map; // get to work
tf::StampedTransform lidar_trans;
tf::StampedTransform cam_trans;
tf::TransformListener *tf_listener;
std::string topics;
Eigen::Map<Eigen::Matrix<char, Eigen::Dynamic, Eigen::Dynamic>>* eigenRep;

float resolution;
float orientation;
int x;
int y;
int length_y;
int width_x;

void frame_callback(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &msg, const std::string &topic)
{
  //transform pointcloud into the occupancy grid, no filtering right now
  bool offMap = false;

  //make transformed clouds
  pcl::PointCloud<pcl::PointXYZ>::Ptr transformed = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>());

    if (msg->header.frame_id == "/scan/pointcloud") {
    pcl_ros::transformPointCloud(*msg, *transformed, lidar_trans);

  } else {
    pcl_ros::transformPointCloud(*msg, *transformed, cam_trans);
  }

  pcl::PointCloud<pcl::PointXYZ>::const_iterator point;
  for (point = transformed->begin(); point < transformed->points.end(); point++)
  {
    int point_x = (int) std::round((point->x / resolution) + x);
    int point_y = (int) std::round((point->y / resolution) + y);

    if(point_x > 0 && point_y > 0 && point_x < length_y && y < width_x)
    {
        (*(eigenRep))(point_x,point_y) = 255;
    } else if(!offMap){
      ROS_WARN_STREAM("Some points out of range, won't be put on map.");
      offMap = true;
    }
  }

  //make image message from img bridge
  std_msgs::Header header; // empty header
  header.stamp = ros::Time::now(); // time
  img_bridge = cv_bridge::CvImage(header, sensor_msgs::image_encodings::MONO8, *published_map);
  img_bridge.toImageMsg(imageBoi); // from cv_bridge to sensor_msgs::Image
  imageBoi.header = header;
  //set fields of map message
  msgBoi.header = header;
  msgBoi.image = imageBoi;
  msgBoi.length = length_y;
  msgBoi.width = width_x;
  msgBoi.resolution = resolution;
  msgBoi.orientation = orientation;
  map_pub.publish(imageBoi);
}

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

  ros::init(argc, argv, "new_mapper");
  ros::NodeHandle nh;
  ros::NodeHandle pNh("~");

  std::list<ros::Subscriber> subs;

  tf_listener = new tf::TransformListener();

  double start_x;
  double start_y;

  pNh.getParam("topics", topics);
  pNh.getParam("occupancy_grid_length", length_y);
  pNh.getParam("occupancy_grid_width", width_x);
  pNh.getParam("qoccupancy_grid_resolution", resolution);
  pNh.getParam("start_X", start_x);
  pNh.getParam("start_Y", start_y);
  pNh.getParam("orientation", orientation);

  length_y = (int) std::round(length_y / resolution);
  width_x = (int) std::round(width_x / resolution);
  x = (int) std::round(start_x / resolution);
  y = (int) std::round(start_y / resolution);

  //set up tokens and get list of subscribers
  std::istringstream iss(topics);
  std::vector<std::string> tokens{ std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>() };

  for (std::string topic : tokens)
  {
    ROS_INFO_STREAM("Mapper subscribing to " << topic);
    subs.push_back(nh.subscribe<pcl::PointCloud<pcl::PointXYZ>>(topic, 1, boost::bind(frame_callback, _1, topic)));
  }

  //init transforms
  ros::Time time = ros::Time::now();
  if (tf_listener->waitForTransform("/odom", "/scan/pointcloud", time, ros::Duration(5.0)))
  {
    tf_listener->lookupTransform("/odom", "/scan/pointcloud", time, lidar_trans);

  }
  if (tf_listener->waitForTransform("/odom", "/usb_cam_center/line_cloud", time, ros::Duration(5.0)))
  {
    tf_listener->lookupTransform("/odom", "/usb_cam_center/line_cloud", time, cam_trans);

  }

  //TODO: Initialize the map variables, not working
  //global_map = Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>(length, width);
  published_map = new cv::Mat(length_y, width_x, CV_8UC1); // I cant instatiate this
  //https://docs.opencv.org/2.4/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html
  eigenRep = new Eigen::Map<Eigen::Matrix<char, Eigen::Dynamic, Eigen::Dynamic>>((char*) published_map, length_y, width_x);
  //https://stackoverflow.com/questions/14783329/opencv-cvmat-and-eigenmatrix

  map_pub = nh.advertise<pcl::PointCloud<pcl::PointXYZRGB>>("/map", 1);

  ros::spin();
}
<commit_msg>Removed unneseccary comments<commit_after>#include <pcl/point_cloud.h>
#include <pcl_ros/point_cloud.h>
#include <ros/publisher.h>
#include <ros/ros.h>
#include <stdlib.h>
#include <Eigen/Core>
#include <opencv2/opencv.hpp>
#include <opencv2/core/eigen.hpp>
#include <pcl_ros/transforms.h>
#include <igvc_msgs/velocity_pair.h>
#include <igvc_msgs/map.h>
#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>

igvc_msgs::map msgBoi;
cv_bridge::CvImage img_bridge;
sensor_msgs::Image imageBoi; // >> message to be sent

ros::Publisher map_pub;
cv::Mat* published_map; // get to work
tf::StampedTransform lidar_trans;
tf::StampedTransform cam_trans;
tf::TransformListener *tf_listener;
std::string topics;
Eigen::Map<Eigen::Matrix<char, Eigen::Dynamic, Eigen::Dynamic>>* eigenRep;

float resolution;
float orientation;
int x;
int y;
int length_y;
int width_x;

void frame_callback(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &msg, const std::string &topic)
{
  //transform pointcloud into the occupancy grid, no filtering right now
  bool offMap = false;

  //make transformed clouds
  pcl::PointCloud<pcl::PointXYZ>::Ptr transformed = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>());

    if (msg->header.frame_id == "/scan/pointcloud") {
    pcl_ros::transformPointCloud(*msg, *transformed, lidar_trans);

  } else {
    pcl_ros::transformPointCloud(*msg, *transformed, cam_trans);
  }

  pcl::PointCloud<pcl::PointXYZ>::const_iterator point;
  for (point = transformed->begin(); point < transformed->points.end(); point++)
  {
    int point_x = (int) std::round((point->x / resolution) + x);
    int point_y = (int) std::round((point->y / resolution) + y);

    if(point_x > 0 && point_y > 0 && point_x < length_y && y < width_x)
    {
        (*(eigenRep))(point_x,point_y) = 255;
    } else if(!offMap){
      ROS_WARN_STREAM("Some points out of range, won't be put on map.");
      offMap = true;
    }
  }

  //make image message from img bridge
  std_msgs::Header header; // empty header
  header.stamp = ros::Time::now(); // time
  img_bridge = cv_bridge::CvImage(header, sensor_msgs::image_encodings::MONO8, *published_map);
  img_bridge.toImageMsg(imageBoi); // from cv_bridge to sensor_msgs::Image
  imageBoi.header = header;
  //set fields of map message
  msgBoi.header = header;
  msgBoi.image = imageBoi;
  msgBoi.length = length_y;
  msgBoi.width = width_x;
  msgBoi.resolution = resolution;
  msgBoi.orientation = orientation;
  map_pub.publish(imageBoi);
}

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

  ros::init(argc, argv, "new_mapper");
  ros::NodeHandle nh;
  ros::NodeHandle pNh("~");

  std::list<ros::Subscriber> subs;

  tf_listener = new tf::TransformListener();

  double start_x;
  double start_y;

  pNh.getParam("topics", topics);
  pNh.getParam("occupancy_grid_length", length_y);
  pNh.getParam("occupancy_grid_width", width_x);
  pNh.getParam("qoccupancy_grid_resolution", resolution);
  pNh.getParam("start_X", start_x);
  pNh.getParam("start_Y", start_y);
  pNh.getParam("orientation", orientation);

  length_y = (int) std::round(length_y / resolution);
  width_x = (int) std::round(width_x / resolution);
  x = (int) std::round(start_x / resolution);
  y = (int) std::round(start_y / resolution);

  //set up tokens and get list of subscribers
  std::istringstream iss(topics);
  std::vector<std::string> tokens{ std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>() };

  for (std::string topic : tokens)
  {
    ROS_INFO_STREAM("Mapper subscribing to " << topic);
    subs.push_back(nh.subscribe<pcl::PointCloud<pcl::PointXYZ>>(topic, 1, boost::bind(frame_callback, _1, topic)));
  }

  //init transforms
  ros::Time time = ros::Time::now();
  if (tf_listener->waitForTransform("/odom", "/scan/pointcloud", time, ros::Duration(5.0)))
  {
    tf_listener->lookupTransform("/odom", "/scan/pointcloud", time, lidar_trans);

  }
  if (tf_listener->waitForTransform("/odom", "/usb_cam_center/line_cloud", time, ros::Duration(5.0)))
  {
    tf_listener->lookupTransform("/odom", "/usb_cam_center/line_cloud", time, cam_trans);

  }

  published_map = new cv::Mat(length_y, width_x, CV_8UC1); // I cant instatiate this
  eigenRep = new Eigen::Map<Eigen::Matrix<char, Eigen::Dynamic, Eigen::Dynamic>>((char*) published_map, length_y, width_x);

  map_pub = nh.advertise<pcl::PointCloud<pcl::PointXYZRGB>>("/map", 1);

  ros::spin();
}
<|endoftext|>


<commit_before><commit_msg>Use thread-safe localtime_r instead of localtime.<commit_after><|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file   mt_queue.hpp
/// \author Serge Aleynikov
//----------------------------------------------------------------------------
/// \brief Producer/consumer queue.
///
/// Based on code from:
/// http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
/// Original version authored by Anthony Williams
/// Modifications by Michael Anderson
/// Modifications by Serge Aleynikov
//----------------------------------------------------------------------------
// Created: 2010-09-15
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#ifndef _UTXX_MT_QUEUE_HPP_
#define _UTXX_MT_QUEUE_HPP_

#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <utxx/compiler_hints.hpp>
#include <deque>
#include <exception>

namespace utxx {

class queue_canceled : public std::exception {};

template<typename Data, typename Alloc = std::allocator<char> >
class concurrent_queue
{
public:
    typedef std::deque<Data, Alloc> queue_type;
private:
    queue_type                  m_queue;
    mutable boost::mutex        m_mutex;
    boost::condition_variable   m_condition_variable;
    bool                        m_is_canceled;

public:
    concurrent_queue()
        : m_queue(), m_mutex()
        , m_condition_variable()
        , m_is_canceled(false)
    {}

    void reset() {
        m_queue.clear();
        m_is_canceled = false;
    }

    bool canceled() const { return m_is_canceled; }

    int enqueue(Data const& data, struct timespec* timeout = NULL) {
        try {
            push(data);
            return 0;
        } catch (queue_canceled&) {
            return -1;
        }
    }

    int dequeue(Data& value) {
        try                     { pop(value);   }
        catch (queue_canceled&) { return -1; }
        return 0;
    }

    int dequeue(Data& value, struct timespec* wait_time) {
        if (!wait_time)
            return dequeue(value);
        boost::posix_time::time_duration timeout(
            boost::posix_time::seconds(wait_time->tv_sec) +
            boost::posix_time::microseconds(wait_time->tv_nsec / 1000));
        try                     { return timed_pop(value, timeout) ? 0 : -1; }
        catch (queue_canceled&) { return -1; }
    }

    void push(Data const& data) {
        {
            boost::mutex::scoped_lock lock(m_mutex);
            if (unlikely(m_is_canceled)) throw queue_canceled();
            m_queue.push_back(data);
        }
        m_condition_variable.notify_one();
    }

    bool empty() const {
        boost::mutex::scoped_lock lock(m_mutex);
        if (unlikely(m_is_canceled)) throw queue_canceled();
        return m_queue.empty();
    }

    bool try_pop(Data& popped_value) {
        boost::mutex::scoped_lock lock(m_mutex);
        if (unlikely(m_is_canceled)) throw queue_canceled();
        if(m_queue.empty())
            return false;

        popped_value=m_queue.front();
        m_queue.pop_front();
        return true;
    }

    /// Wait until the queue is non-empty and dequeue
    /// a single item.
    void pop(Data& popped_value) {
        boost::mutex::scoped_lock lock(m_mutex);

        while(m_queue.empty() && !m_is_canceled)
            m_condition_variable.wait(lock);

        if (unlikely(m_is_canceled)) throw queue_canceled();

        popped_value=m_queue.front();
        m_queue.pop_front();
    }

    /// Wait until the queue is non-empty and dequeue
    /// a single item.
    bool timed_pop(Data& popped_value, const boost::posix_time::time_duration& timeout) {
        boost::mutex::scoped_lock lock(m_mutex);

        if (m_queue.empty() && !m_is_canceled)
            if (!m_condition_variable.timed_wait(lock, timeout))
                return false;

        if (unlikely(m_is_canceled)) throw queue_canceled();

        popped_value=m_queue.front();
        m_queue.pop_front();
        return true;
    }

    /// Wait until the queue is non-empty and dequeue
    /// all pending items.
    queue_type pop_all() {
        boost::mutex::scoped_lock lock(m_mutex);

        while(m_queue.empty() && !m_is_canceled)
            m_condition_variable.wait(lock);

        queue_type retval;
        std::swap(retval, m_queue);
        return retval;
    }

    void terminate() {
        {
            boost::mutex::scoped_lock lock(m_mutex);
            if (m_is_canceled) return;
            m_is_canceled = true;
        }
        m_condition_variable.notify_all();
    }
};

} // namespace utxx

#endif // _UTXX_MT_QUEUE_HPP_
<commit_msg>Update mt_queue.hpp<commit_after>//----------------------------------------------------------------------------
/// \file   mt_queue.hpp
/// \author Serge Aleynikov
//----------------------------------------------------------------------------
/// \brief Producer/consumer queue.
///
/// Based on code from:
/// http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html
/// Original version authored by Anthony Williams
/// Modifications by Michael Anderson
/// Modifications by Serge Aleynikov
//----------------------------------------------------------------------------
// Created: 2010-09-15
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

***** END LICENSE BLOCK *****
*/
#pragma once

#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <utxx/compiler_hints.hpp>
#include <deque>
#include <exception>

namespace utxx {

class queue_canceled : public std::exception {};

template<typename Data, typename Alloc = std::allocator<char> >
class concurrent_queue
{
public:
    typedef std::deque<Data, Alloc> queue_type;
private:
    queue_type                  m_queue;
    mutable boost::mutex        m_mutex;
    boost::condition_variable   m_condition_variable;
    bool                        m_is_canceled;

public:
    concurrent_queue()
        : m_queue(), m_mutex()
        , m_condition_variable()
        , m_is_canceled(false)
    {}

    void reset() {
        m_queue.clear();
        m_is_canceled = false;
    }

    bool canceled() const { return m_is_canceled; }

    int enqueue(Data const& data, struct timespec* timeout = NULL) {
        try {
            push(data);
            return 0;
        } catch (queue_canceled&) {
            return -1;
        }
    }

    int dequeue(Data& value) {
        try                     { pop(value);   }
        catch (queue_canceled&) { return -1; }
        return 0;
    }

    int dequeue(Data& value, struct timespec* wait_time) {
        if (!wait_time)
            return dequeue(value);
        boost::posix_time::time_duration timeout(
            boost::posix_time::seconds(wait_time->tv_sec) +
            boost::posix_time::microseconds(wait_time->tv_nsec / 1000));
        try                     { return timed_pop(value, timeout) ? 0 : -1; }
        catch (queue_canceled&) { return -1; }
    }

    void push(Data const& data) {
        {
            boost::mutex::scoped_lock lock(m_mutex);
            if (unlikely(m_is_canceled)) throw queue_canceled();
            m_queue.push_back(data);
        }
        m_condition_variable.notify_one();
    }

    bool empty() const {
        boost::mutex::scoped_lock lock(m_mutex);
        if (unlikely(m_is_canceled)) throw queue_canceled();
        return m_queue.empty();
    }

    bool try_pop(Data& popped_value) {
        boost::mutex::scoped_lock lock(m_mutex);
        if (unlikely(m_is_canceled)) throw queue_canceled();
        if(m_queue.empty())
            return false;

        popped_value=m_queue.front();
        m_queue.pop_front();
        return true;
    }

    /// Wait until the queue is non-empty and dequeue
    /// a single item.
    void pop(Data& popped_value) {
        boost::mutex::scoped_lock lock(m_mutex);

        while(m_queue.empty() && !m_is_canceled)
            m_condition_variable.wait(lock);

        if (unlikely(m_is_canceled)) throw queue_canceled();

        popped_value=m_queue.front();
        m_queue.pop_front();
    }

    /// Wait until the queue is non-empty and dequeue
    /// a single item.
    bool timed_pop(Data& popped_value, const boost::posix_time::time_duration& timeout) {
        boost::mutex::scoped_lock lock(m_mutex);

        if (m_queue.empty() && !m_is_canceled)
            if (!m_condition_variable.timed_wait(lock, timeout))
                return false;

        if (unlikely(m_is_canceled)) throw queue_canceled();

        popped_value=m_queue.front();
        m_queue.pop_front();
        return true;
    }

    /// Wait until the queue is non-empty and dequeue
    /// all pending items.
    queue_type pop_all() {
        boost::mutex::scoped_lock lock(m_mutex);

        while(m_queue.empty() && !m_is_canceled)
            m_condition_variable.wait(lock);

        queue_type retval;
        std::swap(retval, m_queue);
        return retval;
    }

    void terminate() {
        {
            boost::mutex::scoped_lock lock(m_mutex);
            if (m_is_canceled) return;
            m_is_canceled = true;
        }
        m_condition_variable.notify_all();
    }
};

} // namespace utxx
<|endoftext|>