<commit_before>// Copyright (C) 2016-2017 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef TYPE_SAFE_CONFIG_HPP_INCLUDED
#define TYPE_SAFE_CONFIG_HPP_INCLUDED

#include <cstddef>
#include <cstdlib>

#ifndef TYPE_SAFE_ENABLE_ASSERTIONS
/// Controls whether internal assertions are enabled.
///
/// It is disabled by default.
#define TYPE_SAFE_ENABLE_ASSERTIONS 0
#endif

#ifndef TYPE_SAFE_ENABLE_PRECONDITION_CHECKS
/// Controls whether preconditions are checked.
///
/// It is enabled by default.
#define TYPE_SAFE_ENABLE_PRECONDITION_CHECKS 1
#endif

#ifndef TYPE_SAFE_ENABLE_WRAPPER
/// Controls whether the typedefs in [types.hpp]() use the type safe wrapper types.
///
/// It is enabled by default.
#define TYPE_SAFE_ENABLE_WRAPPER 1
#endif

#ifndef TYPE_SAFE_ARITHMETIC_UB
/// Controls whether [ts::arithmetic_policy_default]() is [ts::undefined_behavior_arithmetic]() or [ts::default_arithmetic]().
///
/// It is [ts::undefined_behavior_arithmetic]() by default.
#define TYPE_SAFE_ARITHMETIC_UB 1
#endif

#ifndef TYPE_SAFE_USE_REF_QUALIFIERS
#if defined(__cpp_ref_qualifiers) && __cpp_ref_qualifiers >= 200710
/// \exclude
#define TYPE_SAFE_USE_REF_QUALIFIERS 1
#elif defined(_MSC_VER) && _MSC_VER >= 1900
#define TYPE_SAFE_USE_REF_QUALIFIERS 1
#else
#define TYPE_SAFE_USE_REF_QUALIFIERS 0
#endif
#endif

#if TYPE_SAFE_USE_REF_QUALIFIERS
/// \exclude
#define TYPE_SAFE_LVALUE_REF &
/// \exclude
#define TYPE_SAFE_RVALUE_REF &&
#else
#define TYPE_SAFE_LVALUE_REF
#define TYPE_SAFE_RVALUE_REF
#endif

#ifndef TYPE_SAFE_USE_NOEXCEPT_DEFAULT

#if defined(__GNUC__) && __GNUC__ < 5
// GCC before 5.0 doesn't handle noexcept and = default properly
/// \exclude
#define TYPE_SAFE_USE_NOEXCEPT_DEFAULT 0
#else
/// \exclude
#define TYPE_SAFE_USE_NOEXCEPT_DEFAULT 1
#endif

#endif

#if TYPE_SAFE_USE_NOEXCEPT_DEFAULT
/// \exclude
#define TYPE_SAFE_NOEXCEPT_DEFAULT(Val) noexcept(Val)
#else
/// \exclude
#define TYPE_SAFE_NOEXCEPT_DEFAULT(Val)
#endif

#ifndef TYPE_SAFE_USE_EXCEPTIONS

#if __cpp_exceptions
/// \exclude
#define TYPE_SAFE_USE_EXCEPTIONS 1
#elif defined(__GNUC__) && defined(__EXCEPTIONS)
/// \exclude
#define TYPE_SAFE_USE_EXCEPTIONS 1
#elif defined(_MSC_VER) && defined(_CPPUNWIND)
/// \exclude
#define TYPE_SAFE_USE_EXCEPTIONS 1
#else
/// \exclude
#define TYPE_SAFE_USE_EXCEPTIONS 0
#endif

#endif

#if TYPE_SAFE_USE_EXCEPTIONS
/// \exclude
#define TYPE_SAFE_THROW(Ex) throw Ex
/// \exclude
#define TYPE_SAFE_TRY try
/// \exclude
#define TYPE_SAFE_CATCH_ALL catch (...)
/// \exclude
#define TYPE_SAFE_RETHROW throw
#else
#define TYPE_SAFE_THROW(Ex) (Ex, std::abort())
#define TYPE_SAFE_TRY if (true)
#define TYPE_SAFE_CATCH_ALL if (false)
#define TYPE_SAFE_RETHROW std::abort()
#endif

/// \entity type_safe
/// \unique_name ts

#endif // TYPE_SAFE_CONFIG_HPP_INCLUDED
<commit_msg>Add TYPE_SAFE_USE_RTTI macro<commit_after>// Copyright (C) 2016-2017 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef TYPE_SAFE_CONFIG_HPP_INCLUDED
#define TYPE_SAFE_CONFIG_HPP_INCLUDED

#include <cstddef>
#include <cstdlib>

#ifndef TYPE_SAFE_ENABLE_ASSERTIONS
/// Controls whether internal assertions are enabled.
///
/// It is disabled by default.
#define TYPE_SAFE_ENABLE_ASSERTIONS 0
#endif

#ifndef TYPE_SAFE_ENABLE_PRECONDITION_CHECKS
/// Controls whether preconditions are checked.
///
/// It is enabled by default.
#define TYPE_SAFE_ENABLE_PRECONDITION_CHECKS 1
#endif

#ifndef TYPE_SAFE_ENABLE_WRAPPER
/// Controls whether the typedefs in [types.hpp]() use the type safe wrapper types.
///
/// It is enabled by default.
#define TYPE_SAFE_ENABLE_WRAPPER 1
#endif

#ifndef TYPE_SAFE_ARITHMETIC_UB
/// Controls whether [ts::arithmetic_policy_default]() is [ts::undefined_behavior_arithmetic]() or [ts::default_arithmetic]().
///
/// It is [ts::undefined_behavior_arithmetic]() by default.
#define TYPE_SAFE_ARITHMETIC_UB 1
#endif

#ifndef TYPE_SAFE_USE_REF_QUALIFIERS
#if defined(__cpp_ref_qualifiers) && __cpp_ref_qualifiers >= 200710
/// \exclude
#define TYPE_SAFE_USE_REF_QUALIFIERS 1
#elif defined(_MSC_VER) && _MSC_VER >= 1900
#define TYPE_SAFE_USE_REF_QUALIFIERS 1
#else
#define TYPE_SAFE_USE_REF_QUALIFIERS 0
#endif
#endif

#if TYPE_SAFE_USE_REF_QUALIFIERS
/// \exclude
#define TYPE_SAFE_LVALUE_REF &
/// \exclude
#define TYPE_SAFE_RVALUE_REF &&
#else
#define TYPE_SAFE_LVALUE_REF
#define TYPE_SAFE_RVALUE_REF
#endif

#ifndef TYPE_SAFE_USE_NOEXCEPT_DEFAULT

#if defined(__GNUC__) && __GNUC__ < 5
// GCC before 5.0 doesn't handle noexcept and = default properly
/// \exclude
#define TYPE_SAFE_USE_NOEXCEPT_DEFAULT 0
#else
/// \exclude
#define TYPE_SAFE_USE_NOEXCEPT_DEFAULT 1
#endif

#endif

#if TYPE_SAFE_USE_NOEXCEPT_DEFAULT
/// \exclude
#define TYPE_SAFE_NOEXCEPT_DEFAULT(Val) noexcept(Val)
#else
/// \exclude
#define TYPE_SAFE_NOEXCEPT_DEFAULT(Val)
#endif

#ifndef TYPE_SAFE_USE_EXCEPTIONS

#if __cpp_exceptions
/// \exclude
#define TYPE_SAFE_USE_EXCEPTIONS 1
#elif defined(__GNUC__) && defined(__EXCEPTIONS)
/// \exclude
#define TYPE_SAFE_USE_EXCEPTIONS 1
#elif defined(_MSC_VER) && defined(_CPPUNWIND)
/// \exclude
#define TYPE_SAFE_USE_EXCEPTIONS 1
#else
/// \exclude
#define TYPE_SAFE_USE_EXCEPTIONS 0
#endif

#endif

#if TYPE_SAFE_USE_EXCEPTIONS
/// \exclude
#define TYPE_SAFE_THROW(Ex) throw Ex
/// \exclude
#define TYPE_SAFE_TRY try
/// \exclude
#define TYPE_SAFE_CATCH_ALL catch (...)
/// \exclude
#define TYPE_SAFE_RETHROW throw
#else
#define TYPE_SAFE_THROW(Ex) (Ex, std::abort())
#define TYPE_SAFE_TRY if (true)
#define TYPE_SAFE_CATCH_ALL if (false)
#define TYPE_SAFE_RETHROW std::abort()
#endif

#ifndef TYPE_SAFE_USE_RTTI

#ifdef __GXX_RTTI
#define TYPE_SAFE_USE_RTTI 1
#elif defined(_CPPRTTI_)
#define TYPE_SAFE_USE_RTTI 1
#else
#define TYPE_SAFE_USE_RTTI 0
#endif

#endif

/// \entity type_safe
/// \unique_name ts

#endif // TYPE_SAFE_CONFIG_HPP_INCLUDED
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>

class BigInteger
{
public:
    BigInteger()
      : digits(1, 0)
    {}

    BigInteger(unsigned int x) {
        do {
            digits.push_back(x % 10);
            x /= 10;
        } while (x > 0);
    }

    BigInteger& operator++() {
        digits[0]++;
        HandleCarry();
        return *this;
    }

    BigInteger operator++(int) {
        BigInteger copy(*this);
        ++copy;
        return copy;
    }

    BigInteger operator/(const BigInteger& o) {
        BigInteger res;
        BigInteger reminder(*this);
        int power = reminder.digits.size() - o.digits.size();
        if (power <= 0) {
            return 0;
        }
        res.digits.resize(power + 1, 0);
        while (reminder > o) {
            for (int d = 1; d <= 10; ++d) {
                BigInteger temp;
                temp.digits.resize(power,  0);
                temp.digits.push_back(d);
                if (temp * o > reminder) {
                    res.digits[power] = d - 1;
                    temp.digits[power] = d - 1;
                    reminder = reminder - temp * o;
                    power--;
                    break;
                }
            }
        }
        res.RemoveLeadingZeroes();
        return res;
    }

    BigInteger operator+(const BigInteger& o) {
        BigInteger res;
        res.digits.resize(std::max(this->digits.size(), o.digits.size()));
        for (int i = 0; i < res.digits.size(); ++i) {
            res.digits[i] = this->GetDigit(i) + o.GetDigit(i);
        }
        res.HandleCarry();
        return res;
    }

    BigInteger operator-(const BigInteger& o) {
        BigInteger res;
        res.digits.resize(std::max(this->digits.size(), o.digits.size()));
        for (int i = 0; i < res.digits.size(); ++i) {
            res.digits[i] = this->GetDigit(i) - o.GetDigit(i);
        }
        res.HandleNegativeCarry();
        res.RemoveLeadingZeroes();
        return res;
    }

    BigInteger operator*(const BigInteger& o) {
        BigInteger res;
        res.digits.resize(this->digits.size() + o.digits.size(), 0);
        for (int i = 0; i < this->digits.size(); ++i) {
            for (int j = 0; j < o.digits.size(); ++j) {
                res.digits[i + j] += this->digits[i] * o.digits[j];
            }
        }
        res.HandleCarry();
        res.RemoveLeadingZeroes();
        return res;
    }

    bool operator==(const BigInteger& o) const{
        if (o.digits.size() != this->digits.size())
            return false;
        for (int i = 0; i < this->digits.size(); ++i) {
            if (o.digits[i] != this->digits[i])
                return false;
        }
        return true;
    }

    bool operator!=(const BigInteger& o) const {
        return !(*this == o);
    }

    bool operator<(const BigInteger& o) const {
        if (this->digits.size() < o.digits.size())
            return true;
        if (this->digits.size() > o.digits.size())
            return false;

        for (int i = this->digits.size() - 1; i >= 0; --i) {
            if (this->digits[i] < o.digits[i])
                return true;
            if (this->digits[i] > o.digits[i])
                return false;
        }
        return false;
    }

    bool operator<=(const BigInteger& o) const{
        return *this < o || *this == o;
    }

    bool operator>(const BigInteger& o) const{
        return o < *this;
    }

    bool operator>=(const BigInteger& o) const{
        return o <= *this;
    }

    friend std::ostream& operator<<(std::ostream& out, const BigInteger& num);
private:
    void HandleCarry() {
        for (int i = 0; i < digits.size(); ++i) {
            int carry = digits[i] / 10;
            digits[i] %= 10;
            if (i == digits.size() - 1 && carry != 0) {
                digits.push_back(carry);
            } else {
                digits[i + 1] += carry;
            }
        }
    }

    void HandleNegativeCarry() {
        // TODO: this function doesn't work for negative numbers
        for (int i = 0; i < digits.size(); ++i) {
            if (digits[i] < 0) {
                digits[i] += 10;
                digits[i + 1]--;
            }
        }
    }

    void RemoveLeadingZeroes() {
        while (this->digits.size() > 1 && this->digits[this->digits.size() - 1] == 0)
            this->digits.pop_back();
    }

    int GetDigit(int idx) const {
        if (idx < 0)
            throw std::exception(); // TODO
        if (idx > digits.size() - 1)
            return 0;
        return digits[idx];
    }
    // Digits in base 10
    // TODO: It is not very memory/cpu efficient
    // Little-Endian-ish
    std::vector<int> digits;
};

std::ostream& operator<<(std::ostream& out, const BigInteger& num){
   for (int i = num.digits.size() - 1; i >= 0; --i) {
       out << num.digits[i];
    }
   return out;
}

int main()
{
    BigInteger x = 1000000000;
    BigInteger y = 1000000000;
    std::cout << x << " " << y << std::endl;
    BigInteger z = x + y;
    std::cout << z << std::endl;
    BigInteger a = z + x + y;
    std::cout << a << std::endl;
    std::cout << (z == 42) << std::endl;
    std::cout << "NON-EQ test" << std::endl;
    std::cout << (z != 42) << std::endl;
    std::cout << "NON-EQ test ended" << std::endl;
    std::cout << (z < 42) << std::endl;
    std::cout << "TEST" << std::endl;
    std::cout << (z + z + 1 < z + z + 2) << std::endl;
    std::cout << "SUBTRACTION TEST" << std::endl;
    BigInteger q = 1700;
    std::cout << q - 18 << std::endl;
    std::cout << "DIVISION TEST" << std::endl;
    BigInteger d = 1280;
    std::cout << d / 14 << std::endl;
}
<commit_msg>Remove this-> (I've been writing too much code in python lately)<commit_after>#include <iostream>
#include <vector>

class BigInteger
{
public:
    BigInteger()
      : digits(1, 0)
    {}

    BigInteger(unsigned int x) {
        do {
            digits.push_back(x % 10);
            x /= 10;
        } while (x > 0);
    }

    BigInteger& operator++() {
        digits[0]++;
        HandleCarry();
        return *this;
    }

    BigInteger operator++(int) {
        BigInteger copy(*this);
        ++copy;
        return copy;
    }

    BigInteger operator/(const BigInteger& o) {
        BigInteger res;
        BigInteger reminder(*this);
        int power = reminder.digits.size() - o.digits.size();
        if (power <= 0) {
            return 0;
        }
        res.digits.resize(power + 1, 0);
        while (reminder > o) {
            for (int d = 1; d <= 10; ++d) {
                BigInteger temp;
                temp.digits.resize(power,  0);
                temp.digits.push_back(d);
                if (temp * o > reminder) {
                    res.digits[power] = d - 1;
                    temp.digits[power] = d - 1;
                    reminder = reminder - temp * o;
                    power--;
                    break;
                }
            }
        }
        res.RemoveLeadingZeroes();
        return res;
    }

    BigInteger operator+(const BigInteger& o) {
        BigInteger res;
        res.digits.resize(std::max(digits.size(), o.digits.size()));
        for (int i = 0; i < res.digits.size(); ++i) {
            res.digits[i] = GetDigit(i) + o.GetDigit(i);
        }
        res.HandleCarry();
        return res;
    }

    BigInteger operator-(const BigInteger& o) {
        BigInteger res;
        res.digits.resize(std::max(digits.size(), o.digits.size()));
        for (int i = 0; i < res.digits.size(); ++i) {
            res.digits[i] = GetDigit(i) - o.GetDigit(i);
        }
        res.HandleNegativeCarry();
        res.RemoveLeadingZeroes();
        return res;
    }

    BigInteger operator*(const BigInteger& o) {
        BigInteger res;
        res.digits.resize(digits.size() + o.digits.size(), 0);
        for (int i = 0; i < digits.size(); ++i) {
            for (int j = 0; j < o.digits.size(); ++j) {
                res.digits[i + j] += digits[i] * o.digits[j];
            }
        }
        res.HandleCarry();
        res.RemoveLeadingZeroes();
        return res;
    }

    bool operator==(const BigInteger& o) const{
        if (o.digits.size() != digits.size())
            return false;
        for (int i = 0; i < digits.size(); ++i) {
            if (o.digits[i] != digits[i])
                return false;
        }
        return true;
    }

    bool operator!=(const BigInteger& o) const {
        return !(*this == o);
    }

    bool operator<(const BigInteger& o) const {
        if (digits.size() < o.digits.size())
            return true;
        if (digits.size() > o.digits.size())
            return false;

        for (int i = digits.size() - 1; i >= 0; --i) {
            if (digits[i] < o.digits[i])
                return true;
            if (digits[i] > o.digits[i])
                return false;
        }
        return false;
    }

    bool operator<=(const BigInteger& o) const{
        return *this < o || *this == o;
    }

    bool operator>(const BigInteger& o) const{
        return o < *this;
    }

    bool operator>=(const BigInteger& o) const{
        return o <= *this;
    }

    friend std::ostream& operator<<(std::ostream& out, const BigInteger& num);
private:
    void HandleCarry() {
        for (int i = 0; i < digits.size(); ++i) {
            int carry = digits[i] / 10;
            digits[i] %= 10;
            if (i == digits.size() - 1 && carry != 0) {
                digits.push_back(carry);
            } else {
                digits[i + 1] += carry;
            }
        }
    }

    void HandleNegativeCarry() {
        // TODO: this function doesn't work for negative numbers
        for (int i = 0; i < digits.size(); ++i) {
            if (digits[i] < 0) {
                digits[i] += 10;
                digits[i + 1]--;
            }
        }
    }

    void RemoveLeadingZeroes() {
        while (digits.size() > 1 && digits[digits.size() - 1] == 0)
            digits.pop_back();
    }

    int GetDigit(int idx) const {
        if (idx < 0)
            throw std::exception(); // TODO
        if (idx > digits.size() - 1)
            return 0;
        return digits[idx];
    }
    // Digits in base 10
    // TODO: It is not very memory/cpu efficient
    // Little-Endian-ish
    std::vector<int> digits;
};

std::ostream& operator<<(std::ostream& out, const BigInteger& num){
   for (int i = num.digits.size() - 1; i >= 0; --i) {
       out << num.digits[i];
    }
   return out;
}

int main()
{
    BigInteger x = 1000000000;
    BigInteger y = 1000000000;
    std::cout << x << " " << y << std::endl;
    BigInteger z = x + y;
    std::cout << z << std::endl;
    BigInteger a = z + x + y;
    std::cout << a << std::endl;
    std::cout << (z == 42) << std::endl;
    std::cout << "NON-EQ test" << std::endl;
    std::cout << (z != 42) << std::endl;
    std::cout << "NON-EQ test ended" << std::endl;
    std::cout << (z < 42) << std::endl;
    std::cout << "TEST" << std::endl;
    std::cout << (z + z + 1 < z + z + 2) << std::endl;
    std::cout << "SUBTRACTION TEST" << std::endl;
    BigInteger q = 1700;
    std::cout << q - 18 << std::endl;
    std::cout << "DIVISION TEST" << std::endl;
    BigInteger d = 1280;
    std::cout << d / 14 << std::endl;
}
<|endoftext|>


<commit_before>#ifndef _EULERANGLESYAWPITCHROLL_H_
#define _EULERANGLESYAWPITCHROLL_H_

#include "RotationalKinematics.hpp"

namespace sm { namespace kinematics {

  /**
   * @class EulerAnglesYawPitchRoll
   * This is the standard Rotation sequence for aerospace vehicles.
   *
   * Passing this the parameters [yaw, pitch, roll] of a vehicle frame, F_v,
   * with respect to an inertial frame, F_i, returns the rotation matrix,
   * C_iv, the rotation that takes vectors from F_v, to F_i.
   *
   * Similarly passing the rotation matrix C_iv to this class will cause
   * return the vector [heading, pitch, roll] where these represent the usual
   * meaning with respect to aerospace vehicles.
   *
   * heading: positive is vehicle nose left (counter clockwise).
   * pitch:   positive is vehicle nose down.
   * roll:    positive is left wing up.
   *
   */
    class EulerAnglesYawPitchRoll : public RotationalKinematics
    {
    public:
      virtual ~EulerAnglesYawPitchRoll();
      // Three functions that must be implemented.
      virtual Eigen::Matrix3d parametersToRotationMatrix(const Eigen::Vector3d & parameters, Eigen::Matrix3d * S = NULL) const;
      virtual Eigen::Vector3d rotationMatrixToParameters(const Eigen::Matrix3d & rotationMatrix) const;
      virtual Eigen::Matrix3d parametersToSMatrix(const Eigen::Vector3d & parameters) const;
      virtual Eigen::Vector3d angularVelocityAndJacobian(const Eigen::Vector3d & p, const Eigen::Vector3d & pdot, Eigen::Matrix<double,3,6> * Jacobian) const;
    private:
      // A helper function
      Eigen::Matrix3d buildSMatrix(double sz, double cz, double sy, double cy) const;
    };

  }} // namespace sm::kinematics

#endif /* _EULERANGLESYAWPITCHROLL_H_ */
<commit_msg>Added some comments to the yaw/pitch/roll file<commit_after>#ifndef _EULERANGLESYAWPITCHROLL_H_
#define _EULERANGLESYAWPITCHROLL_H_

#include "RotationalKinematics.hpp"

namespace sm { namespace kinematics {

  /**
   * @class EulerAnglesYawPitchRoll
   * This is the standard Rotation sequence for aerospace vehicles.
   *
   * Passing this the parameters [yaw, pitch, roll] of a vehicle frame, F_v,
   * with respect to an inertial frame, F_i, returns the rotation matrix,
   * C_iv, the rotation that takes vectors from F_v, to F_i.
   *
   * Similarly passing the rotation matrix C_iv to this class will cause
   * return the vector [heading, pitch, roll] where these represent the usual
   * meaning with respect to aerospace vehicles.
   *
   * This assumes that the vehicle frame has:
   * x-axis pointing to the front.
   * y-axis pointing to the left.
   * z-axis pointing up.
   *
   * heading: positive is vehicle nose left (counter clockwise).
   * pitch:   positive is vehicle nose down.
   * roll:    positive is left wing up.
   *
   */
    class EulerAnglesYawPitchRoll : public RotationalKinematics
    {
    public:
      virtual ~EulerAnglesYawPitchRoll();
      // Three functions that must be implemented.
      virtual Eigen::Matrix3d parametersToRotationMatrix(const Eigen::Vector3d & parameters, Eigen::Matrix3d * S = NULL) const;
      virtual Eigen::Vector3d rotationMatrixToParameters(const Eigen::Matrix3d & rotationMatrix) const;
      virtual Eigen::Matrix3d parametersToSMatrix(const Eigen::Vector3d & parameters) const;
      virtual Eigen::Vector3d angularVelocityAndJacobian(const Eigen::Vector3d & p, const Eigen::Vector3d & pdot, Eigen::Matrix<double,3,6> * Jacobian) const;
    private:
      // A helper function
      Eigen::Matrix3d buildSMatrix(double sz, double cz, double sy, double cy) const;
    };

  }} // namespace sm::kinematics

#endif /* _EULERANGLESYAWPITCHROLL_H_ */
<|endoftext|>


<commit_before>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2020 Martin Davis
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/geom/Geometry.h>
#include <geos/geom/Point.h>
#include <geos/geom/LineString.h>
#include <geos/geom/LinearRing.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/GeometryCollection.h>
#include <geos/geom/IntersectionMatrix.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/prep/PreparedGeometry.h>
#include <geos/geom/prep/PreparedGeometryFactory.h>
#include <geos/operation/relate/RelateOp.h>
#include <geos/operation/valid/MakeValid.h>
#include <geos/operation/overlayng/OverlayNG.h>
#include <geos/operation/polygonize/Polygonizer.h>
#include <geos/precision/GeometryPrecisionReducer.h>

#include "GeomFunction.h"

#include <sstream>

using geos::operation::overlayng::OverlayNG;

/* static private */
std::map<std::string, GeomFunction*> GeomFunction::registry;

static std::unique_ptr<const PreparedGeometry> prepGeomCache;
static Geometry *cacheKey;

/* static */
void
GeomFunction::init()
{
    add("area",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getArea() );
        });
    add("boundary",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getBoundary() );
        });
    add("buffer", "cmputes the buffer of geometry A", 1, 1,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->buffer( d ) );
        });
    add("centroid",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getCentroid() );
        });
    add("copy",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->clone() );
        });
    add("convexHull",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->convexHull() );
        });
    add("contains", "tests if geometry A contains geometry B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->contains( geomB.get() ) );
        });
    add("covers", "tests if geometry A covers geometry B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->covers( geomB.get() ) );
        });
     add("envelope",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getCentroid() );
        });
    add("interiorPoint",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getInteriorPoint() );
        });
    add("intersects", "tests if geometry A and B intersect", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->intersects( geomB.get() ) );
        });
    add("isValid", "tests if geometry A is valid", 1, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->isValid() );
        });
    add("length",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getLength() );
        });
    add("makeValid",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geos::operation::valid::MakeValid().build( geom.get() ) );
        });

    add("polygonize",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geos::operation::polygonize::Polygonizer p;
            p.add(geom.get());

            auto polys = p.getPolygons();
            std::vector<geom::Geometry*>* geoms = new std::vector<geom::Geometry*>;
            for(unsigned int i = 0; i < polys.size(); i++) {
                geoms->push_back(polys[i].release());
            }
            auto factory = geom->getFactory();
            Geometry * res = factory->createGeometryCollection(geoms);
            return new Result( res) ;
        });

    add("containsPrep", "tests if geometry A contains geometry B, using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->contains( geomB.get() ) );
        });
    add("containsProperlyPrep", "tests if geometry A properly contains geometry B using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->containsProperly( geomB.get() ) );
        });
    add("coversPrep", "tests if geometry A covers geometry B using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->covers( geomB.get() ) );
        });
    add("intersectsPrep", "tests if geometry A intersects geometry B using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->intersects( geomB.get() ) );
        });

    add("reducePrecision", "reduces precision of geometry to a precision scale factor", 1, 1,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            PrecisionModel pm(d);
            return new Result( geos::precision::GeometryPrecisionReducer::reduce( *geom, pm ) );
        });
    add("relate", "computes DE-9IM matrix for geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            std::unique_ptr<geom::IntersectionMatrix> im(geom->relate( geomB.get() ));
            return new Result( im->toString() );
        });

    add("difference", "computes difference of geometry A from B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->difference( geomB.get() ) );
        });
    add("intersection", "computes intersection of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->intersection( geomB.get() ) );
        });
    add("symDifference", "computes symmetric difference of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->symDifference( geomB.get() ) );
        });
    add("unaryUnion",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->Union() );
        });
    add("union", "computes union of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->Union( geomB.get() ) );
        });

    add("differenceSR", "computes difference of geometry A from B rounding to a precision scale factor", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geom::PrecisionModel pm(d);
            return new Result( OverlayNG::overlay(geom.get(), geomB.get(), OverlayNG::DIFFERENCE, &pm) );
        });
    add("intersectionSR", "computes intersection of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geom::PrecisionModel pm(d);
            return new Result( OverlayNG::overlay(geom.get(), geomB.get(), OverlayNG::INTERSECTION, &pm) );
        });
    add("symDifferenceSR", "computes symmetric difference of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geom::PrecisionModel pm(d);
            return new Result( OverlayNG::overlay(geom.get(), geomB.get(), OverlayNG::SYMDIFFERENCE, &pm) );
        });
    add("unionSR", "computes union of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geom::PrecisionModel pm(d);
            return new Result( OverlayNG::overlay(geom.get(), geomB.get(), OverlayNG::UNION, &pm) );
        });

}

/* static */
GeomFunction*
GeomFunction::find(std::string name)
{
    if (registry.count(name) == 0)
        return nullptr;
    return registry[name];
}

/* static */
void
GeomFunction::add(std::string name, geomFunSig geomfun)
{
    add(name,
        "computes " + name + " for geometry A",
        1, 0, geomfun);
}

/* static */
void
GeomFunction::add(std::string name,
                    std::string desc,
                    int nGeomParam,
                    int nParam,
                    geomFunSig geomfun)
{
    auto fun = new GeomFunction();
    fun->funName = name;
    fun->description = desc;
    fun->geomfun = geomfun;
    fun->numGeomParam = nGeomParam;
    fun->numParam = nParam;

    registry.insert( std::pair<std::string, GeomFunction *>(name, fun) );
}

std::string GeomFunction::name()
{
    return funName;
}

bool GeomFunction::isBinary()
{
    return numGeomParam == 2;
}

std::string GeomFunction::signature() {
    std::string sig = funName + " A";
    if (isBinary()) {
        sig += " B";
    }
    if (numParam > 0) sig += " N";
    return sig;
}

std::vector<std::string>
GeomFunction::list()
{
    std::vector<std::string> list;
    for (auto itr = registry.begin(); itr != registry.end(); ++itr) {
        auto fun = itr->second;
        auto desc = fun->signature() + " - " + fun->description;
        // TODO: add display of function signature
        list.push_back( desc );
    }
    return list;
}

Result * GeomFunction::execute( const std::unique_ptr<Geometry>& geomA, const std::unique_ptr<Geometry>& geomB, double d )
{
    return geomfun( geomA, geomB, d );
}

//===============================================

Result::Result(bool val)
{
    valBool = val;
    typeCode = typeBool;
}

Result::Result(int  val)
{
    valInt = val;
    typeCode = typeInt;
}

Result::Result(double val)
{
    valDouble = val;
    typeCode = typeDouble;
}

Result::Result(std::string val)
{
    valStr = val;
    typeCode = typeString;
}

Result::Result(std::unique_ptr<geom::Geometry> val)
{
    valGeom = std::move(val);
    typeCode = typeGeometry;
}

Result::Result(Geometry * val)
{
    valGeom = std::unique_ptr<Geometry>(val);
    typeCode = typeGeometry;
}

Result::~Result()
{
}

bool
Result::isGeometry() {
    return typeCode == typeGeometry;
}

std::string
Result::toString() {
    std::stringstream converter;
    switch (typeCode) {
    case typeBool:
        converter << std::boolalpha << valBool;
        return converter.str();

    case typeInt:
        converter << valInt;
        return converter.str();

    case typeDouble:
        converter << valDouble;
        return converter.str();

    case typeString:
        return valStr;

    case typeGeometry:
        if (valGeom == nullptr)
            return "null";
        return valGeom->toString();
    }
    return "Value for Unknonwn type";
}

std::string
Result::metadata() {
    switch (typeCode) {
    case typeBool:    return "bool";
    case typeInt:     return "int";
    case typeDouble:  return "double";
    case typeString:  return "string";

    case typeGeometry:
        if (valGeom == nullptr)
            return "null";
        return valGeom->getGeometryType() + "( " + std::to_string( valGeom->getNumPoints() ) + " )";
    }
    return "Unknonwn type";
}
<commit_msg>Add geosop distance and nearestPoints operations<commit_after>/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2020 Martin Davis
 *
 * This is free software; you can redistribute and/or modify it under
 * the terms of the GNU Lesser General Public Licence as published
 * by the Free Software Foundation.
 * See the COPYING file for more information.
 *
 **********************************************************************/

#include <geos/geom/Geometry.h>
#include <geos/geom/Point.h>
#include <geos/geom/LineString.h>
#include <geos/geom/LinearRing.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/GeometryCollection.h>
#include <geos/geom/IntersectionMatrix.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/prep/PreparedGeometry.h>
#include <geos/geom/prep/PreparedGeometryFactory.h>
#include <geos/operation/distance/DistanceOp.h>
#include <geos/operation/relate/RelateOp.h>
#include <geos/operation/valid/MakeValid.h>
#include <geos/operation/overlayng/OverlayNG.h>
#include <geos/operation/polygonize/Polygonizer.h>
#include <geos/precision/GeometryPrecisionReducer.h>

#include "GeomFunction.h"

#include <sstream>

using geos::operation::overlayng::OverlayNG;

/* static private */
std::map<std::string, GeomFunction*> GeomFunction::registry;

static std::unique_ptr<const PreparedGeometry> prepGeomCache;
static Geometry *cacheKey;

/* static */
void
GeomFunction::init()
{
    add("area",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getArea() );
        });
    add("boundary",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getBoundary() );
        });
    add("buffer", "cmputes the buffer of geometry A", 1, 1,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->buffer( d ) );
        });
    add("centroid",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getCentroid() );
        });
    add("copy",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->clone() );
        });
    add("convexHull",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->convexHull() );
        });
    add("contains", "tests if geometry A contains geometry B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->contains( geomB.get() ) );
        });
    add("covers", "tests if geometry A covers geometry B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->covers( geomB.get() ) );
        });

    add("distance", "computes distance between geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->distance( geomB.get() ) );
        });

     add("envelope",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getCentroid() );
        });

    add("interiorPoint",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getInteriorPoint() );
        });

    add("intersects", "tests if geometry A and B intersect", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->intersects( geomB.get() ) );
        });

    add("isValid", "tests if geometry A is valid", 1, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->isValid() );
        });

    add("length",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->getLength() );
        });

    add("makeValid",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geos::operation::valid::MakeValid().build( geom.get() ) );
        });

    add("nearestPoints", "computes nearest points of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            std::unique_ptr<CoordinateSequence> cs = geos::operation::distance::DistanceOp::nearestPoints(geom.get(), geomB.get());
            auto factory = geom->getFactory();
            auto res = factory->createLineString( std::move(cs) );
            return new Result( std::move(res) );
        });

    add("polygonize",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geos::operation::polygonize::Polygonizer p;
            p.add(geom.get());

            auto polys = p.getPolygons();
            std::vector<geom::Geometry*>* geoms = new std::vector<geom::Geometry*>;
            for(unsigned int i = 0; i < polys.size(); i++) {
                geoms->push_back(polys[i].release());
            }
            auto factory = geom->getFactory();
            Geometry * res = factory->createGeometryCollection(geoms);
            return new Result( res) ;
        });

    add("containsPrep", "tests if geometry A contains geometry B, using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->contains( geomB.get() ) );
        });
    add("containsProperlyPrep", "tests if geometry A properly contains geometry B using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->containsProperly( geomB.get() ) );
        });
    add("coversPrep", "tests if geometry A covers geometry B using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->covers( geomB.get() ) );
        });
    add("intersectsPrep", "tests if geometry A intersects B using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->intersects( geomB.get() ) );
        });

    add("distancePrep", "computes distance between geometry A and B using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            return new Result( prepGeomCache->distance( geomB.get() ) );
        });
    add("nearestPointsPrep", "computes nearest points of geometry A and B using PreparedGeometry", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            if (cacheKey == nullptr || cacheKey != geom.get()) {
                auto pg = std::unique_ptr<const PreparedGeometry>(
                    PreparedGeometryFactory::prepare( geom.get()) );
                prepGeomCache = std::move( pg );
                cacheKey = geom.get();
            }
            auto cs = prepGeomCache->nearestPoints( geomB.get() );
            auto factory = geom->getFactory();
            auto res = factory->createLineString( std::move(cs) );
            return new Result( std::move(res) );
        });

    add("reducePrecision", "reduces precision of geometry to a precision scale factor", 1, 1,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            PrecisionModel pm(d);
            return new Result( geos::precision::GeometryPrecisionReducer::reduce( *geom, pm ) );
        });
    add("relate", "computes DE-9IM matrix for geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            std::unique_ptr<geom::IntersectionMatrix> im(geom->relate( geomB.get() ));
            return new Result( im->toString() );
        });

    add("difference", "computes difference of geometry A from B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->difference( geomB.get() ) );
        });
    add("intersection", "computes intersection of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->intersection( geomB.get() ) );
        });
    add("symDifference", "computes symmetric difference of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->symDifference( geomB.get() ) );
        });
    add("unaryUnion",
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->Union() );
        });
    add("union", "computes union of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            return new Result( geom->Union( geomB.get() ) );
        });

    add("differenceSR", "computes difference of geometry A from B rounding to a precision scale factor", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geom::PrecisionModel pm(d);
            return new Result( OverlayNG::overlay(geom.get(), geomB.get(), OverlayNG::DIFFERENCE, &pm) );
        });
    add("intersectionSR", "computes intersection of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geom::PrecisionModel pm(d);
            return new Result( OverlayNG::overlay(geom.get(), geomB.get(), OverlayNG::INTERSECTION, &pm) );
        });
    add("symDifferenceSR", "computes symmetric difference of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geom::PrecisionModel pm(d);
            return new Result( OverlayNG::overlay(geom.get(), geomB.get(), OverlayNG::SYMDIFFERENCE, &pm) );
        });
    add("unionSR", "computes union of geometry A and B", 2, 0,
        [](const std::unique_ptr<Geometry>& geom, const std::unique_ptr<Geometry>& geomB, double d)->Result* {
            geom::PrecisionModel pm(d);
            return new Result( OverlayNG::overlay(geom.get(), geomB.get(), OverlayNG::UNION, &pm) );
        });

}

/* static */
GeomFunction*
GeomFunction::find(std::string name)
{
    if (registry.count(name) == 0)
        return nullptr;
    return registry[name];
}

/* static */
void
GeomFunction::add(std::string name, geomFunSig geomfun)
{
    add(name,
        "computes " + name + " for geometry A",
        1, 0, geomfun);
}

/* static */
void
GeomFunction::add(std::string name,
                    std::string desc,
                    int nGeomParam,
                    int nParam,
                    geomFunSig geomfun)
{
    auto fun = new GeomFunction();
    fun->funName = name;
    fun->description = desc;
    fun->geomfun = geomfun;
    fun->numGeomParam = nGeomParam;
    fun->numParam = nParam;

    registry.insert( std::pair<std::string, GeomFunction *>(name, fun) );
}

std::string GeomFunction::name()
{
    return funName;
}

bool GeomFunction::isBinary()
{
    return numGeomParam == 2;
}

std::string GeomFunction::signature() {
    std::string sig = funName + " A";
    if (isBinary()) {
        sig += " B";
    }
    if (numParam > 0) sig += " N";
    return sig;
}

std::vector<std::string>
GeomFunction::list()
{
    std::vector<std::string> list;
    for (auto itr = registry.begin(); itr != registry.end(); ++itr) {
        auto fun = itr->second;
        auto desc = fun->signature() + " - " + fun->description;
        // TODO: add display of function signature
        list.push_back( desc );
    }
    return list;
}

Result * GeomFunction::execute( const std::unique_ptr<Geometry>& geomA, const std::unique_ptr<Geometry>& geomB, double d )
{
    return geomfun( geomA, geomB, d );
}

//===============================================

Result::Result(bool val)
{
    valBool = val;
    typeCode = typeBool;
}

Result::Result(int  val)
{
    valInt = val;
    typeCode = typeInt;
}

Result::Result(double val)
{
    valDouble = val;
    typeCode = typeDouble;
}

Result::Result(std::string val)
{
    valStr = val;
    typeCode = typeString;
}

Result::Result(std::unique_ptr<geom::Geometry> val)
{
    valGeom = std::move(val);
    typeCode = typeGeometry;
}

Result::Result(Geometry * val)
{
    valGeom = std::unique_ptr<Geometry>(val);
    typeCode = typeGeometry;
}

Result::~Result()
{
}

bool
Result::isGeometry() {
    return typeCode == typeGeometry;
}

std::string
Result::toString() {
    std::stringstream converter;
    switch (typeCode) {
    case typeBool:
        converter << std::boolalpha << valBool;
        return converter.str();

    case typeInt:
        converter << valInt;
        return converter.str();

    case typeDouble:
        converter << valDouble;
        return converter.str();

    case typeString:
        return valStr;

    case typeGeometry:
        if (valGeom == nullptr)
            return "null";
        return valGeom->toString();
    }
    return "Value for Unknonwn type";
}

std::string
Result::metadata() {
    switch (typeCode) {
    case typeBool:    return "bool";
    case typeInt:     return "int";
    case typeDouble:  return "double";
    case typeString:  return "string";

    case typeGeometry:
        if (valGeom == nullptr)
            return "null";
        return valGeom->getGeometryType() + "( " + std::to_string( valGeom->getNumPoints() ) + " )";
    }
    return "Unknonwn type";
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: timenode.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef OOX_DRAWINGML_TIMENODE_HXX
#define OOX_DRAWINGML_TIMENODE_HXX

#include <boost/shared_ptr.hpp>
#include <vector>
#include <list>
#include <rtl/ustring.hxx>

#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/animations/XAnimationNode.hpp>
#include "oox/helper/propertymap.hxx"
#include "oox/ppt/slidetransition.hxx"
#include "oox/ppt/slidepersist.hxx"
#include "oox/ppt/animationspersist.hxx"
#include "oox/ppt/timenode.hxx"

namespace oox { namespace ppt {

    class TimeNode;
    class SlideTransition;

    typedef boost::shared_ptr< TimeNode > TimeNodePtr;
    typedef ::std::list< TimeNodePtr > TimeNodePtrList;

    class TimeNode
    {
    public:
        TimeNode( sal_Int16 nNodeType );
        virtual ~TimeNode();

        NodePropertyMap & getNodeProperties() { return maNodeProperties; }
        PropertyMap & getUserData() { return maUserData; }
        void addChild( const TimeNodePtr & pChildPtr )
            { maChilds.push_back( pChildPtr ); }

        TimeNodePtrList & getChilds()
            { return maChilds; }

        void setId( sal_Int32 nId );
        const ::rtl::OUString & getId() const { return msId; }

        void addNode( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > &rxModel,
                                    const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& rxNode,
                                    const SlidePersistPtr & slide);
        // data setters
        void setTo( const ::com::sun::star::uno::Any & aTo );
        void setFrom( const ::com::sun::star::uno::Any & aFrom );
        void setBy( const ::com::sun::star::uno::Any & aBy );
        void setTransitionFilter( const SlideTransition & aTransition)
            { maTransitionFilter = aTransition; }

        void setNode( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > &rxModel,
                      const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode, const SlidePersistPtr & pSlide );

        AnimTargetElementPtr getTarget()
            {
                if( !mpTarget )
                    mpTarget.reset( new AnimTargetElement );
                return mpTarget;
            }

        AnimationConditionList &getStartCondition()
            { return maStCondList; }
        AnimationConditionList &getEndCondition()
            { return maEndCondList; }
        AnimationConditionList &getNextCondition()
            { return maNextCondList; }
        AnimationConditionList &getPrevCondition()
            { return maPrevCondList; }
        AnimationCondition & getEndSyncValue()
            { mbHasEndSyncValue = true; return maEndSyncValue; }
    protected:

        static rtl::OUString getServiceName( sal_Int16 nNodeType );

        ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >
        createAndInsert( const rtl::OUString& rServiceName,
                                         const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > &rxModel,
                                         const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& rxNode );

    private:
        const sal_Int16 mnNodeType;

        TimeNodePtrList maChilds;

        rtl::OUString   msId;
        NodePropertyMap            maNodeProperties;
        PropertyMap                maUserData; // a sequence to be stored as "UserData" property
        SlideTransition            maTransitionFilter;
        AnimTargetElementPtr       mpTarget;
        bool                       mbHasEndSyncValue; // set to true if we try to get the endSync.
        AnimationCondition         maEndSyncValue;
        AnimationConditionList     maStCondList, maEndCondList;
        AnimationConditionList     maPrevCondList, maNextCondList;
    };

} }

#endif
<commit_msg>INTEGRATION: CWS xmlfilter06 (1.3.8); FILE MERGED 2008/06/06 16:27:52 dr 1.3.8.1: chart formatting: builtin line/fill/effect styles, manual line formatting<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: timenode.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef OOX_DRAWINGML_TIMENODE_HXX
#define OOX_DRAWINGML_TIMENODE_HXX

#include <boost/shared_ptr.hpp>
#include <vector>
#include <list>
#include <rtl/ustring.hxx>

#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/animations/XAnimationNode.hpp>
#include "oox/helper/propertymap.hxx"
#include "oox/ppt/slidetransition.hxx"
#include "oox/ppt/slidepersist.hxx"
#include "oox/ppt/animationspersist.hxx"
#include "oox/ppt/timenode.hxx"

namespace oox { namespace ppt {

    class TimeNode;
    class SlideTransition;

    typedef boost::shared_ptr< TimeNode > TimeNodePtr;
    typedef ::std::list< TimeNodePtr > TimeNodePtrList;

    class TimeNode
    {
    public:
        TimeNode( sal_Int16 nNodeType );
        virtual ~TimeNode();

        NodePropertyMap & getNodeProperties() { return maNodeProperties; }
        PropertyMap & getUserData() { return maUserData; }
        void addChild( const TimeNodePtr & pChildPtr )
            { maChildren.push_back( pChildPtr ); }

        TimeNodePtrList & getChildren()
            { return maChildren; }

        void setId( sal_Int32 nId );
        const ::rtl::OUString & getId() const { return msId; }

        void addNode( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > &rxModel,
                                    const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& rxNode,
                                    const SlidePersistPtr & slide);
        // data setters
        void setTo( const ::com::sun::star::uno::Any & aTo );
        void setFrom( const ::com::sun::star::uno::Any & aFrom );
        void setBy( const ::com::sun::star::uno::Any & aBy );
        void setTransitionFilter( const SlideTransition & aTransition)
            { maTransitionFilter = aTransition; }

        void setNode( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > &rxModel,
                      const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode, const SlidePersistPtr & pSlide );

        AnimTargetElementPtr getTarget()
            {
                if( !mpTarget )
                    mpTarget.reset( new AnimTargetElement );
                return mpTarget;
            }

        AnimationConditionList &getStartCondition()
            { return maStCondList; }
        AnimationConditionList &getEndCondition()
            { return maEndCondList; }
        AnimationConditionList &getNextCondition()
            { return maNextCondList; }
        AnimationConditionList &getPrevCondition()
            { return maPrevCondList; }
        AnimationCondition & getEndSyncValue()
            { mbHasEndSyncValue = true; return maEndSyncValue; }
    protected:

        static rtl::OUString getServiceName( sal_Int16 nNodeType );

        ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >
        createAndInsert( const rtl::OUString& rServiceName,
                                         const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > &rxModel,
                                         const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& rxNode );

    private:
        const sal_Int16 mnNodeType;

        TimeNodePtrList maChildren;

        rtl::OUString   msId;
        NodePropertyMap            maNodeProperties;
        PropertyMap                maUserData; // a sequence to be stored as "UserData" property
        SlideTransition            maTransitionFilter;
        AnimTargetElementPtr       mpTarget;
        bool                       mbHasEndSyncValue; // set to true if we try to get the endSync.
        AnimationCondition         maEndSyncValue;
        AnimationConditionList     maStCondList, maEndCondList;
        AnimationConditionList     maPrevCondList, maNextCondList;
    };

} }

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
/*
 * @file        Cynara.cpp
 * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
 * @version     1.0
 * @brief       This file implements main class of cynara service
 */

#include <memory>
#include <stddef.h>

#include <exceptions/InitException.h>

#include <logic/Logic.h>
#include <sockets/SocketManager.h>
#include <storage/InMemoryStorageBackend.h>
#include <storage/Storage.h>
#include <storage/StorageBackend.h>

#include "Cynara.h"

namespace Cynara {

Cynara::Cynara()
    : m_logic(nullptr), m_socketManager(nullptr), m_storage(nullptr), m_storageBackend(nullptr) {
}

Cynara::~Cynara() {
    finalize();
}

void Cynara::init(void) {
    m_logic = std::make_shared<Logic>();
    m_socketManager = std::make_shared<SocketManager>();
    m_storageBackend = std::make_shared<InMemoryStorageBackend>();
    m_storage = std::make_shared<Storage>(*m_storageBackend);

    m_logic->bindStorage(m_storage);
    m_logic->bindSocketManager(m_socketManager);

    m_socketManager->bindLogic(m_logic);
}

void Cynara::run(void) {
    m_socketManager->run();
}

void Cynara::finalize(void) {
    m_logic->unbindAll();
    m_socketManager->unbindAll();

    m_logic.reset();
    m_socketManager.reset();
    m_storageBackend.reset();
    m_storage.reset();
}

} // namespace Cynara
<commit_msg>Fix shared pointers access in Cynara class<commit_after>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
/*
 * @file        Cynara.cpp
 * @author      Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
 * @version     1.0
 * @brief       This file implements main class of cynara service
 */

#include <memory>
#include <stddef.h>

#include <exceptions/InitException.h>

#include <logic/Logic.h>
#include <sockets/SocketManager.h>
#include <storage/InMemoryStorageBackend.h>
#include <storage/Storage.h>
#include <storage/StorageBackend.h>

#include "Cynara.h"

namespace Cynara {

Cynara::Cynara()
    : m_logic(nullptr), m_socketManager(nullptr), m_storage(nullptr), m_storageBackend(nullptr) {
}

Cynara::~Cynara() {
    finalize();
}

void Cynara::init(void) {
    m_logic = std::make_shared<Logic>();
    m_socketManager = std::make_shared<SocketManager>();
    m_storageBackend = std::make_shared<InMemoryStorageBackend>();
    m_storage = std::make_shared<Storage>(*m_storageBackend);

    m_logic->bindStorage(m_storage);
    m_logic->bindSocketManager(m_socketManager);

    m_socketManager->bindLogic(m_logic);
}

void Cynara::run(void) {
    if (!m_socketManager) {
        throw InitException();
    }

    m_socketManager->run();
}

void Cynara::finalize(void) {
    if (m_logic) {
        m_logic->unbindAll();
    }

    if (m_socketManager) {
        m_socketManager->unbindAll();
    }

    m_logic.reset();
    m_socketManager.reset();
    m_storageBackend.reset();
    m_storage.reset();
}

} // namespace Cynara
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2004-2013 ZNC, see the NOTICE file for details.
 * Copyright (C) 2013 Rasmus Eskola <fruitiex@gmail.com>
 * based on sample.cpp sample module code
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <znc/FileUtils.h>
#include <znc/Client.h>
#include <znc/Chan.h>
#include <znc/User.h>
#include <znc/IRCNetwork.h>
#include <znc/Modules.h>
#include <dirent.h>
#include <vector>
#include <algorithm>

class CBacklogMod : public CModule {
public:
    MODCONSTRUCTOR(CBacklogMod) {}

    virtual bool OnLoad(const CString& sArgs, CString& sMessage);
    virtual ~CBacklogMod();
    virtual void OnModCommand(const CString& sCommand);

private:
    bool inChan(const CString& Chan);
};

bool CBacklogMod::OnLoad(const CString& sArgs, CString& sMessage) {
    CString LogPath = sArgs;

    if(LogPath.empty()) {
        LogPath = GetNV("LogPath");
        if(LogPath.empty()) {
            // TODO: guess logpath?
            PutModule("LogPath is empty, set it with the LogPath command (help for more info)");
        }
    } else {
        SetNV("LogPath", LogPath);
        PutModule("LogPath set to: " + LogPath);
    }
    return true;
}

CBacklogMod::~CBacklogMod() {
}

void CBacklogMod::OnModCommand(const CString& sCommand) {
    CString Arg = sCommand.Token(1);
    if (sCommand.Token(0).Equals("help")) {
        // TODO: proper help text, look how AddHelpCommand() does it in other ZNC code
        PutModule("Usage:");
        PutModule("<window-name> [num-lines] (e.g. #foo 42)");
        PutModule("");
        PutModule("Commands:");
        PutModule("Help (print this text)");
        PutModule("LogPath <path> (use keywords $USER, $NETWORK, $WINDOW and an asterisk * for date)");
        PutModule("PrintStatusMsgs true/false (print join/part/rename messages)");
        return;
    } else if (sCommand.Token(0).Equals("logpath")) {
        if(Arg.empty()) {
            PutModule("Usage: LogPath <path> (use keywords $USER, $NETWORK, $WINDOW and an asterisk * for date:)");
            PutModule("Current LogPath is set to: " + GetNV("LogPath"));
            return;
        }

        CString LogPath = sCommand.Token(1, true);
        SetNV("LogPath", LogPath);
        PutModule("LogPath set to: " + LogPath);
        return;
    } else if (sCommand.Token(0).Equals("PrintStatusMsgs")) {
        if(Arg.empty() || (!Arg.Equals("true", true) && !Arg.Equals("false", true))) {
            PutModule("Usage: PrintStatusMsgs true/false");
            return;
        }

        SetNV("PrintStatusMsgs", Arg);
        PutModule("PrintStatusMsgs set to: " + Arg);
        return;
    }

    // TODO: handle these differently depending on how the module was loaded
    CString User = (m_pUser ? m_pUser->GetUserName() : "UNKNOWN");
    CString Network = (m_pNetwork ? m_pNetwork->GetName() : "znc");
    CString Channel = sCommand.Token(0);

    int printedLines = 0;
    int reqLines = sCommand.Token(1).ToInt();
    if(reqLines <= 0) {
        reqLines = 150;
    }
    reqLines = std::max(std::min(reqLines, 1000), 1);

    CString Path = GetNV("LogPath").substr(); // make copy
    Path.Replace("$NETWORK", Network);
    Path.Replace("$WINDOW", Channel);
    Path.Replace("$USER", User);

    CString DirPath = Path.substr(0, Path.find_last_of("/"));
    CString FilePath;

    std::vector<CString> FileList;
    std::vector<CString> LinesToPrint;

    // gather list of all log files for requested channel/window
    DIR *dir;
    struct dirent *ent;
    if ((dir = opendir (DirPath.c_str())) != NULL) {
        while ((ent = readdir (dir)) != NULL) {
            FilePath = DirPath + "/" + ent->d_name;
            //PutModule("DEBUG: " + FilePath + " " + Path);
            if(FilePath.AsLower().StrCmp(Path.AsLower(), Path.find_last_of("*")) == 0) {
                FileList.push_back(FilePath);
            }
        }
        closedir (dir);
    } else {
        PutModule("Could not list directory " + DirPath + ": " + strerror(errno));
        return;
    }

    std::sort(FileList.begin(), FileList.end());

    // loop through list of log files one by one starting from most recent...
    for (std::vector<CString>::reverse_iterator it = FileList.rbegin(); it != FileList.rend(); ++it) {
        CFile LogFile(*it);
        CString Line;
        std::vector<CString> Lines;

        if (LogFile.Open()) {
            while (LogFile.ReadLine(Line)) {
                try {
                    // is line a part/join/rename etc message (nick ***), do we want to print it?
                    // find nick by finding first whitespace, then moving one char right
                    if(Line.at(Line.find_first_of(' ') + 1) == '*' && !GetNV("PrintStatusMsgs").ToBool()) {
                        continue;
                    }

                    Lines.push_back(Line);
                } catch (int e) {
                    // malformed log line, ignore
                    PutModule("Malformed log line found in " + *it + ": " + Line);
                }
            }
        } else {
            PutModule("Could not open log file [" + sCommand + "]: " + strerror(errno));
            continue;
        }

        LogFile.Close();

        // loop through Lines in reverse order, push to LinesToPrint
        for (std::vector<CString>::reverse_iterator itl = Lines.rbegin(); itl != Lines.rend(); ++itl) {
            LinesToPrint.push_back(*itl);
            printedLines++;

            if(printedLines >= reqLines) {
                break;
            }
        }

        if(printedLines >= reqLines) {
            break;
        }
    }

    if(printedLines == 0) {
        PutModule("No log files found for window " + Channel + " in " + DirPath + "/");
        return;
    } else {
        m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + Channel + " :Backlog playback...", GetClient());
    }

    // now actually print
    for (std::vector<CString>::reverse_iterator it = LinesToPrint.rbegin(); it != LinesToPrint.rend(); ++it) {
        CString Line = *it;
        size_t FirstWS = Line.find_first_of(' '); // position of first whitespace char in line
        size_t NickLen = 3;
        CString Nick = "***";

        try {
            // a log line looks like: [HH:MM:SS] <Nick> Message
            // < and > are illegal characters in nicknames, so we can
            // search for these
            if(Line.at(FirstWS + 1) == '<') { // normal message
                // nicklen includes surrounding < >
                NickLen = Line.find_first_of('>') - Line.find_first_of('<') + 1;
                // but we don't want them in Nick so subtract by two
                Nick = Line.substr(FirstWS + 2, NickLen - 2);
            }

            m_pNetwork->PutUser(":" + Nick + "!znc@znc.in PRIVMSG " + Channel + " :" + Line.substr(0, FirstWS) + Line.substr(FirstWS + NickLen + 1, Line.npos), GetClient());
        } catch (int e) {
            PutModule("Malformed log line! " + Line);
        }
    }

    m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + Channel + " :" + "Playback Complete.", GetClient());
}

bool CBacklogMod::inChan(const CString& Chan) {
    const std::vector <CChan*>& vChans (m_pNetwork->GetChans());

    for (std::vector<CChan*>::const_iterator it = vChans.begin(); it != vChans.end(); ++it) {
        CChan *curChan = *it;
        if(Chan.StrCmp(curChan->GetName()) == 0) {
            return true;
        }
    }

    return false;
}

template<> void TModInfo<CBacklogMod>(CModInfo& Info) {
    Info.AddType(CModInfo::NetworkModule);
    Info.AddType(CModInfo::GlobalModule);
    Info.SetWikiPage("backlog");
    Info.SetArgsHelpText("Takes as optional argument (and if given, sets) the log path, use keywords: $USER, $NETWORK and $WINDOW");
    Info.SetHasArgs(true);
}

NETWORKMODULEDEFS(CBacklogMod, "Module for getting the last X lines of a channels log.")
<commit_msg>get rid of unnecessary function<commit_after>/*
 * Copyright (C) 2004-2013 ZNC, see the NOTICE file for details.
 * Copyright (C) 2013 Rasmus Eskola <fruitiex@gmail.com>
 * based on sample.cpp sample module code
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <znc/FileUtils.h>
#include <znc/Client.h>
#include <znc/Chan.h>
#include <znc/User.h>
#include <znc/IRCNetwork.h>
#include <znc/Modules.h>
#include <dirent.h>
#include <vector>
#include <algorithm>

class CBacklogMod : public CModule {
public:
    MODCONSTRUCTOR(CBacklogMod) {}

    virtual bool OnLoad(const CString& sArgs, CString& sMessage);
    virtual ~CBacklogMod();
    virtual void OnModCommand(const CString& sCommand);
};

bool CBacklogMod::OnLoad(const CString& sArgs, CString& sMessage) {
    CString LogPath = sArgs;

    if(LogPath.empty()) {
        LogPath = GetNV("LogPath");
        if(LogPath.empty()) {
            // TODO: guess logpath?
            PutModule("LogPath is empty, set it with the LogPath command (help for more info)");
        }
    } else {
        SetNV("LogPath", LogPath);
        PutModule("LogPath set to: " + LogPath);
    }
    return true;
}

CBacklogMod::~CBacklogMod() {
}

void CBacklogMod::OnModCommand(const CString& sCommand) {
    CString Arg = sCommand.Token(1);
    if (sCommand.Token(0).Equals("help")) {
        // TODO: proper help text, look how AddHelpCommand() does it in other ZNC code
        PutModule("Usage:");
        PutModule("<window-name> [num-lines] (e.g. #foo 42)");
        PutModule("");
        PutModule("Commands:");
        PutModule("Help (print this text)");
        PutModule("LogPath <path> (use keywords $USER, $NETWORK, $WINDOW and an asterisk * for date)");
        PutModule("PrintStatusMsgs true/false (print join/part/rename messages)");
        return;
    } else if (sCommand.Token(0).Equals("logpath")) {
        if(Arg.empty()) {
            PutModule("Usage: LogPath <path> (use keywords $USER, $NETWORK, $WINDOW and an asterisk * for date:)");
            PutModule("Current LogPath is set to: " + GetNV("LogPath"));
            return;
        }

        CString LogPath = sCommand.Token(1, true);
        SetNV("LogPath", LogPath);
        PutModule("LogPath set to: " + LogPath);
        return;
    } else if (sCommand.Token(0).Equals("PrintStatusMsgs")) {
        if(Arg.empty() || (!Arg.Equals("true", true) && !Arg.Equals("false", true))) {
            PutModule("Usage: PrintStatusMsgs true/false");
            return;
        }

        SetNV("PrintStatusMsgs", Arg);
        PutModule("PrintStatusMsgs set to: " + Arg);
        return;
    }

    // TODO: handle these differently depending on how the module was loaded
    CString User = (m_pUser ? m_pUser->GetUserName() : "UNKNOWN");
    CString Network = (m_pNetwork ? m_pNetwork->GetName() : "znc");
    CString Channel = sCommand.Token(0);

    int printedLines = 0;
    int reqLines = sCommand.Token(1).ToInt();
    if(reqLines <= 0) {
        reqLines = 150;
    }
    reqLines = std::max(std::min(reqLines, 1000), 1);

    CString Path = GetNV("LogPath").substr(); // make copy
    Path.Replace("$NETWORK", Network);
    Path.Replace("$WINDOW", Channel);
    Path.Replace("$USER", User);

    CString DirPath = Path.substr(0, Path.find_last_of("/"));
    CString FilePath;

    std::vector<CString> FileList;
    std::vector<CString> LinesToPrint;

    // gather list of all log files for requested channel/window
    DIR *dir;
    struct dirent *ent;
    if ((dir = opendir (DirPath.c_str())) != NULL) {
        while ((ent = readdir (dir)) != NULL) {
            FilePath = DirPath + "/" + ent->d_name;
            //PutModule("DEBUG: " + FilePath + " " + Path);
            if(FilePath.AsLower().StrCmp(Path.AsLower(), Path.find_last_of("*")) == 0) {
                FileList.push_back(FilePath);
            }
        }
        closedir (dir);
    } else {
        PutModule("Could not list directory " + DirPath + ": " + strerror(errno));
        return;
    }

    std::sort(FileList.begin(), FileList.end());

    // loop through list of log files one by one starting from most recent...
    for (std::vector<CString>::reverse_iterator it = FileList.rbegin(); it != FileList.rend(); ++it) {
        CFile LogFile(*it);
        CString Line;
        std::vector<CString> Lines;

        if (LogFile.Open()) {
            while (LogFile.ReadLine(Line)) {
                try {
                    // is line a part/join/rename etc message (nick ***), do we want to print it?
                    // find nick by finding first whitespace, then moving one char right
                    if(Line.at(Line.find_first_of(' ') + 1) == '*' && !GetNV("PrintStatusMsgs").ToBool()) {
                        continue;
                    }

                    Lines.push_back(Line);
                } catch (int e) {
                    // malformed log line, ignore
                    PutModule("Malformed log line found in " + *it + ": " + Line);
                }
            }
        } else {
            PutModule("Could not open log file [" + sCommand + "]: " + strerror(errno));
            continue;
        }

        LogFile.Close();

        // loop through Lines in reverse order, push to LinesToPrint
        for (std::vector<CString>::reverse_iterator itl = Lines.rbegin(); itl != Lines.rend(); ++itl) {
            LinesToPrint.push_back(*itl);
            printedLines++;

            if(printedLines >= reqLines) {
                break;
            }
        }

        if(printedLines >= reqLines) {
            break;
        }
    }

    if(printedLines == 0) {
        PutModule("No log files found for window " + Channel + " in " + DirPath + "/");
        return;
    } else {
        m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + Channel + " :Backlog playback...", GetClient());
    }

    // now actually print
    for (std::vector<CString>::reverse_iterator it = LinesToPrint.rbegin(); it != LinesToPrint.rend(); ++it) {
        CString Line = *it;
        size_t FirstWS = Line.find_first_of(' '); // position of first whitespace char in line
        size_t NickLen = 3;
        CString Nick = "***";

        try {
            // a log line looks like: [HH:MM:SS] <Nick> Message
            // < and > are illegal characters in nicknames, so we can
            // search for these
            if(Line.at(FirstWS + 1) == '<') { // normal message
                // nicklen includes surrounding < >
                NickLen = Line.find_first_of('>') - Line.find_first_of('<') + 1;
                // but we don't want them in Nick so subtract by two
                Nick = Line.substr(FirstWS + 2, NickLen - 2);
            }

            m_pNetwork->PutUser(":" + Nick + "!znc@znc.in PRIVMSG " + Channel + " :" + Line.substr(0, FirstWS) + Line.substr(FirstWS + NickLen + 1, Line.npos), GetClient());
        } catch (int e) {
            PutModule("Malformed log line! " + Line);
        }
    }

    m_pNetwork->PutUser(":***!znc@znc.in PRIVMSG " + Channel + " :" + "Playback Complete.", GetClient());
}

template<> void TModInfo<CBacklogMod>(CModInfo& Info) {
    Info.AddType(CModInfo::NetworkModule);
    Info.AddType(CModInfo::GlobalModule);
    Info.SetWikiPage("backlog");
    Info.SetArgsHelpText("Takes as optional argument (and if given, sets) the log path, use keywords: $USER, $NETWORK and $WINDOW");
    Info.SetHasArgs(true);
}

NETWORKMODULEDEFS(CBacklogMod, "Module for getting the last X lines of a channels log.")
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// FIXME: This file shall contain the decl of cling::Jupyter in a future
// revision!
//#include "cling/Interpreter/Jupyter/Kernel.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Value.h"
#include "cling/MetaProcessor/MetaProcessor.h"
#include "cling/Utils/Output.h"

#include "llvm/Support/raw_ostream.h"

#include <map>
#include <string>
#include <cstring>
#ifndef LLVM_ON_WIN32
# include <unistd.h>
#else
# include <io.h>
# define write _write
#endif

// FIXME: should be moved into a Jupyter interp struct that then gets returned
// from create.
int pipeToJupyterFD = -1;

namespace cling {
  namespace Jupyter {
    struct MIMEDataRef {
      const char* m_Data;
      const long m_Size;

      MIMEDataRef(const std::string& str):
      m_Data(str.c_str()), m_Size((long)str.length() + 1) {}
      MIMEDataRef(const char* str):
      MIMEDataRef(std::string(str)) {}
      MIMEDataRef(const char* data, long size):
      m_Data(data), m_Size(size) {}
    };

    /// Push MIME stuff to Jupyter. To be called from user code.
    ///\param contentDict - dictionary of MIME type versus content. E.g.
    /// {{"text/html", {"

", }}
    ///\returns `false` if the output could not be sent.
    bool pushOutput(const std::map<std::string, MIMEDataRef> contentDict) {

      // Pipe sees (all numbers are longs, except for the first:
      // - num bytes in a long (sent as a single unsigned char!)
      // - num elements of the MIME dictionary; Jupyter selects one to display.
      // For each MIME dictionary element:
      //   - size of MIME type string  (including the terminating 0)
      //   - MIME type as 0-terminated string
      //   - size of MIME data buffer (including the terminating 0 for
      //     0-terminated strings)
      //   - MIME data buffer

      // Write number of dictionary elements (and the size of that number in a
      // char)
      unsigned char sizeLong = sizeof(long);
      if (write(pipeToJupyterFD, &sizeLong, 1) != 1)
        return false;
      long dictSize = contentDict.size();
      if (write(pipeToJupyterFD, &dictSize, sizeof(long)) != sizeof(long))
        return false;

      for (auto iContent: contentDict) {
        const std::string& mimeType = iContent.first;
        long mimeTypeSize = (long)mimeType.size();
        if (write(pipeToJupyterFD, &mimeTypeSize, sizeof(long)) != sizeof(long))
          return false;
        if (write(pipeToJupyterFD, mimeType.c_str(), mimeType.size() + 1)
            != (long)(mimeType.size() + 1))
          return false;
        const MIMEDataRef& mimeData = iContent.second;
        if (write(pipeToJupyterFD, &mimeData.m_Size, sizeof(long))
            != sizeof(long))
          return false;
        if (write(pipeToJupyterFD, mimeData.m_Data, mimeData.m_Size)
            != mimeData.m_Size)
          return false;
      }
      return true;
    }
  } // namespace Jupyter
} // namespace cling

extern "C" {
///\{
///\name Cling4CTypes
/// The Python compatible view of cling

/// The MetaProcessor cast to void*
using TheMetaProcessor = void;

/// Create an interpreter object.
TheMetaProcessor*
cling_create(int argc, const char *argv[], const char* llvmdir, int pipefd) {
  pipeToJupyterFD = pipefd;
  auto I = new cling::Interpreter(argc, argv, llvmdir);
  return new cling::MetaProcessor(*I, cling::errs());
}

/// Destroy the interpreter.
void cling_destroy(TheMetaProcessor *metaProc) {
  cling::MetaProcessor *M = (cling::MetaProcessor*)metaProc;
  cling::Interpreter *I = const_cast<cling::Interpreter*>(&M->getInterpreter());
  delete M;
  delete I;
}

/// Stringify a cling::Value
static std::string ValueToString(const cling::Value& V) {
  std::string valueString;
  {
    llvm::raw_string_ostream os(valueString);
    V.print(os);
  }
  return valueString;
}

/// Evaluate a string of code. Returns nullptr on failure.
/// Returns a string representation of the expression (can be "") on success.
char* cling_eval(TheMetaProcessor *metaProc, const char *code) {
  cling::MetaProcessor *M = (cling::MetaProcessor*)metaProc;
  cling::Value V;
  cling::Interpreter::CompilationResult Res;
  if (M->process(code, Res, &V)) {
    cling::Jupyter::pushOutput({{"text/html", "Incomplete input! Ignored."}});
    M->cancelContinuation();
    return nullptr;
  }
  if (Res != cling::Interpreter::kSuccess)
    return nullptr;

  if (!V.isValid())
    return strdup("");
  return strdup(ValueToString(V).c_str());
}

void cling_eval_free(char* str) {
  free(str);
}

/// Code completion interfaces.

/// Start completion of code. Returns a handle to be passed to
/// cling_complete_next() to iterate over the completion options. Returns nulptr
/// if no completions are known.
void* cling_complete_start(const char* code) {
  return new int(42);
}

/// Grab the next completion of some code. Returns nullptr if none is left.
const char* cling_complete_next(void* completionHandle) {
  int* counter = (int*) completionHandle;
  if (++(*counter) > 43) {
    delete counter;
    return nullptr;
  }
  return "COMPLETE!";
}

///\}

} // extern "C"
<commit_msg>Do not echo expression results; kernel handles it.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

// FIXME: This file shall contain the decl of cling::Jupyter in a future
// revision!
//#include "cling/Interpreter/Jupyter/Kernel.h"

#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/Value.h"
#include "cling/MetaProcessor/MetaProcessor.h"
#include "cling/Utils/Output.h"

#include "llvm/Support/raw_ostream.h"

#include <map>
#include <string>
#include <cstring>
#ifndef LLVM_ON_WIN32
# include <unistd.h>
#else
# include <io.h>
# define write _write
#endif

// FIXME: should be moved into a Jupyter interp struct that then gets returned
// from create.
int pipeToJupyterFD = -1;

namespace cling {
  namespace Jupyter {
    struct MIMEDataRef {
      const char* m_Data;
      const long m_Size;

      MIMEDataRef(const std::string& str):
      m_Data(str.c_str()), m_Size((long)str.length() + 1) {}
      MIMEDataRef(const char* str):
      MIMEDataRef(std::string(str)) {}
      MIMEDataRef(const char* data, long size):
      m_Data(data), m_Size(size) {}
    };

    /// Push MIME stuff to Jupyter. To be called from user code.
    ///\param contentDict - dictionary of MIME type versus content. E.g.
    /// {{"text/html", {"

", }}
    ///\returns `false` if the output could not be sent.
    bool pushOutput(const std::map<std::string, MIMEDataRef> contentDict) {

      // Pipe sees (all numbers are longs, except for the first:
      // - num bytes in a long (sent as a single unsigned char!)
      // - num elements of the MIME dictionary; Jupyter selects one to display.
      // For each MIME dictionary element:
      //   - size of MIME type string  (including the terminating 0)
      //   - MIME type as 0-terminated string
      //   - size of MIME data buffer (including the terminating 0 for
      //     0-terminated strings)
      //   - MIME data buffer

      // Write number of dictionary elements (and the size of that number in a
      // char)
      unsigned char sizeLong = sizeof(long);
      if (write(pipeToJupyterFD, &sizeLong, 1) != 1)
        return false;
      long dictSize = contentDict.size();
      if (write(pipeToJupyterFD, &dictSize, sizeof(long)) != sizeof(long))
        return false;

      for (auto iContent: contentDict) {
        const std::string& mimeType = iContent.first;
        long mimeTypeSize = (long)mimeType.size();
        if (write(pipeToJupyterFD, &mimeTypeSize, sizeof(long)) != sizeof(long))
          return false;
        if (write(pipeToJupyterFD, mimeType.c_str(), mimeType.size() + 1)
            != (long)(mimeType.size() + 1))
          return false;
        const MIMEDataRef& mimeData = iContent.second;
        if (write(pipeToJupyterFD, &mimeData.m_Size, sizeof(long))
            != sizeof(long))
          return false;
        if (write(pipeToJupyterFD, mimeData.m_Data, mimeData.m_Size)
            != mimeData.m_Size)
          return false;
      }
      return true;
    }
  } // namespace Jupyter
} // namespace cling

extern "C" {
///\{
///\name Cling4CTypes
/// The Python compatible view of cling

/// The MetaProcessor cast to void*
using TheMetaProcessor = void;

/// Create an interpreter object.
TheMetaProcessor*
cling_create(int argc, const char *argv[], const char* llvmdir, int pipefd) {
  pipeToJupyterFD = pipefd;
  auto I = new cling::Interpreter(argc, argv, llvmdir);
  return new cling::MetaProcessor(*I, cling::errs());
}

/// Destroy the interpreter.
void cling_destroy(TheMetaProcessor *metaProc) {
  cling::MetaProcessor *M = (cling::MetaProcessor*)metaProc;
  cling::Interpreter *I = const_cast<cling::Interpreter*>(&M->getInterpreter());
  delete M;
  delete I;
}

/// Stringify a cling::Value
static std::string ValueToString(const cling::Value& V) {
  std::string valueString;
  {
    llvm::raw_string_ostream os(valueString);
    V.print(os);
  }
  return valueString;
}

/// Evaluate a string of code. Returns nullptr on failure.
/// Returns a string representation of the expression (can be "") on success.
char* cling_eval(TheMetaProcessor *metaProc, const char *code) {
  cling::MetaProcessor *M = (cling::MetaProcessor*)metaProc;
  cling::Value V;
  cling::Interpreter::CompilationResult Res;
  if (M->process(code, Res, &V, /*disableValuePrinting*/ true)) {
    cling::Jupyter::pushOutput({{"text/html", "Incomplete input! Ignored."}});
    M->cancelContinuation();
    return nullptr;
  }
  if (Res != cling::Interpreter::kSuccess)
    return nullptr;

  if (!V.isValid())
    return strdup("");
  return strdup(ValueToString(V).c_str());
}

void cling_eval_free(char* str) {
  free(str);
}

/// Code completion interfaces.

/// Start completion of code. Returns a handle to be passed to
/// cling_complete_next() to iterate over the completion options. Returns nulptr
/// if no completions are known.
void* cling_complete_start(const char* code) {
  return new int(42);
}

/// Grab the next completion of some code. Returns nullptr if none is left.
const char* cling_complete_next(void* completionHandle) {
  int* counter = (int*) completionHandle;
  if (++(*counter) > 43) {
    delete counter;
    return nullptr;
  }
  return "COMPLETE!";
}

///\}

} // extern "C"
<|endoftext|>