<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2014 Max-Planck-Institute for Intelligent Systems,
 *                     University of Southern California
 *    Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 *
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 */

/**
 * @date 05/25/2014
 * @author Manuel Wuthrich (manuel.wuthrich@gmail.com)
 * Max-Planck-Institute for Intelligent Systems, University of Southern California
 */

#ifndef FAST_FILTERING_MODELS_PROCESS_MODELS_DAMPED_WIENER_PROCESS_MODEL_HPP
#define FAST_FILTERING_MODELS_PROCESS_MODELS_DAMPED_WIENER_PROCESS_MODEL_HPP

//TODO: THIS IS A LINEAR GAUSSIAN PROCESS, THIS CLASS SHOULD DISAPPEAR

#include <Eigen/Dense>

#include <fl/util/assertions.hpp>
#include <fl/distribution/gaussian.hpp>
#include <fl/model/process/process_model_interface.hpp>

namespace fl
{

/// \todo MISSING DOC. MISSING UTESTS

// Forward declarations
template <typename State> class DampedWienerProcessModel;

/**
 * DampedWienerProcess distribution traits specialization
 * \internal
 */
template <typename State_>
struct Traits<DampedWienerProcessModel<State_>>
{
    typedef State_                                              State;
    typedef typename State::Scalar                              Scalar;
    typedef Eigen::Matrix<Scalar, State::SizeAtCompileTime, 1>  Input;
    typedef Eigen::Matrix<Scalar, State::SizeAtCompileTime, 1>  Noise;

    typedef Gaussian<Noise> GaussianType;
    typedef typename GaussianType::SecondMoment SecondMoment;

    typedef StandardGaussianMapping<State, Noise> GaussianMappingBase;
    typedef ProcessModelInterface<State, Noise, Input> ProcessInterfaceBase;
};

/**
 * \class DampedWienerProcess
 *
 * \ingroup process_models
 */
template <typename State>
class DampedWienerProcessModel:
        public Traits<DampedWienerProcessModel<State>>::GaussianMappingBase,
        public Traits<DampedWienerProcessModel<State>>::ProcessInterfaceBase
{
public:
    typedef DampedWienerProcessModel<State> This;

    typedef typename Traits<This>::Scalar         Scalar;
    typedef typename Traits<This>::SecondMoment       SecondMoment;
    typedef typename Traits<This>::Input          Input;
    typedef typename Traits<This>::Noise          Noise;
    typedef typename Traits<This>::GaussianType   GaussianType;

public:
    explicit DampedWienerProcessModel(size_t dim = DimensionOf<State>())
        : Traits<This>::GaussianMappingBase(dim),
          gaussian_(dim)
    {
    }

    virtual ~DampedWienerProcessModel() { }

    virtual State map_standard_normal(const Noise& sample) const
    {
        return gaussian_.map_standard_normal(sample);
    }

    virtual void condition(const Scalar&  delta_time,
                           const State&  state,
                           const Input&   input)
    {
        gaussian_.mean(mean(delta_time, state, input));
        gaussian_.diagonal_covariance(covariance(delta_time));
    }

    virtual void Parameters(const Scalar& damping,
                            const SecondMoment& noise_covariance)
    {
        damping_ = damping;
        noise_covariance_ = noise_covariance;
    }

    virtual unsigned dimension() const
    {
        return this->standard_variate_dimension();
    }

    /* interface API */
    virtual State predict_state(double delta_time,
                                const State& state,
                                const Noise& noise,
                                const Input& input)
    {
        condition(delta_time, state, input);

        return map_standard_normal(noise);
    }

    virtual size_t state_dimension() const
    {
        return this->standard_variate_dimension();
    }

    virtual size_t noise_dimension() const
    {
        return this->standard_variate_dimension();
    }

    virtual size_t input_dimension() const
    {
        return this->standard_variate_dimension();
    }

private:
    State mean(const Scalar& delta_time,
                    const State& state,
                    const Input& input)
    {
        if(damping_ == 0)
            return state + delta_time * input;

        State state_expectation = (1.0 - exp(-damping_*delta_time)) / damping_ * input +
                                              exp(-damping_*delta_time)  * state;

        // if the damping_ is too small, the result might be nan, we thus return the limit for damping_ -> 0
        if(!std::isfinite(state_expectation.norm()))
            state_expectation = state + delta_time * input;

        return state_expectation;
    }

    SecondMoment covariance(const Scalar& delta_time)
    {
        if(damping_ == 0)
            return delta_time * noise_covariance_;

        Scalar factor = (1.0 - exp(-2.0*damping_*delta_time))/(2.0*damping_);
        if(!std::isfinite(factor))
            factor = delta_time;

        return factor * noise_covariance_;
    }

private:
    // conditional
    GaussianType gaussian_;

    // parameters
    Scalar damping_;
    SecondMoment noise_covariance_;
};

}

#endif
<commit_msg>Added first doc draft to DampedWienerProcessModel<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file damped_wiener_process_model.hpp
 * \date 05/25/2014
 * \author Manuel Wuthrich (manuel.wuthrich@gmail.com)
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__MODEL__PROCESS__DAMPED_WIENER_PROCESS_MODEL_HPP
#define FL__MODEL__PROCESS__DAMPED_WIENER_PROCESS_MODEL_HPP

#include <Eigen/Dense>

#include <fl/util/assertions.hpp>
#include <fl/distribution/gaussian.hpp>
#include <fl/model/process/process_model_interface.hpp>

namespace fl
{

// Forward declarations
template <typename State> class DampedWienerProcessModel;

/**
 * DampedWienerProcess process model traits. This trait definition contains
 * all types used internally within the linear model. Additionally, it provides
 * the types needed externally to use the model.
 */
template <typename State_>
struct Traits<DampedWienerProcessModel<State_>>
{
    /*
     * Required types
     *
     * - Scalar
     * - State
     * - Input
     * - Noise
     */
    typedef State_ State;
    typedef typename State::Scalar Scalar;
    typedef Eigen::Matrix<Scalar, State::SizeAtCompileTime, 1>  Input;
    typedef Eigen::Matrix<Scalar, State::SizeAtCompileTime, 1>  Noise;

    /* Model interfaces*/
    /**
     * \brief Basic process model interface type defined using the State, Noise
     *        and Input types of this process
     */
    typedef ProcessModelInterface<State, Noise, Input> ProcessInterfaceBase;

    /**
     * \brief Interface definition used to map standard normal noise variates
     *        onto a state variate
     */
    typedef StandardGaussianMapping<State, Noise> GaussianMappingBase;

    /** \cond INTERNAL */
    typedef Gaussian<Noise> NoiseGaussian;
    typedef typename NoiseGaussian::SecondMoment SecondMoment;
    /** \endcond */
};

/**
 * \ingroup process_models
 * \sa Traits<DampedWienerProcessModel<State>>
 * \todo What does IntegratedDampedWienerProcessModel represent?
 * \todo missing unit tests
 *
 * \brief Represents ...
 *
 * \details
 */
template <typename State>
class DampedWienerProcessModel
        : public Traits<DampedWienerProcessModel<State>>::GaussianMappingBase,
          public Traits<DampedWienerProcessModel<State>>::ProcessInterfaceBase
{
public:
    typedef DampedWienerProcessModel<State> This;

    typedef typename Traits<This>::Scalar         Scalar;
    typedef typename Traits<This>::SecondMoment   SecondMoment;
    typedef typename Traits<This>::Input          Input;
    typedef typename Traits<This>::Noise          Noise;
    typedef typename Traits<This>::NoiseGaussian   NoiseGaussian;

public:

    /**
     * Constructor of a fixed-size and dynamic-size DampedWiener
     * process model.
     *
     * \param dim   State dimension which must be specified for dynamic-size
     *              states. If the state has a compile-time fix size, the \c dim
     *              argument is deduced automatically
     */
    explicit
    DampedWienerProcessModel(size_t dim = DimensionOf<State>())
        : Traits<This>::GaussianMappingBase(dim),
          gaussian_(dim)
    {
        static_assert(IsDynamic<State::SizeAtCompileTime>() ||
                      DimensionOf<State>() > 0,
                      "Static state dimension must be greater than zero.");
    }

    /**
     * \brief  Overridable default destructor
     */
    virtual ~DampedWienerProcessModel() { }

    /**
     * Mapps the specified noise sample onto the a state variate.
     *
     * \param sample    Noise variate
     *
     * \return A state variate given the noise sample
     */
    virtual State map_standard_normal(const Noise& sample) const
    {
        return gaussian_.map_standard_normal(sample);
    }

    /**
     * \copydoc ProcessModelInterface::condition
     */
    virtual void condition(const Scalar&  delta_time,
                           const State&  state,
                           const Input&   input)
    {
        gaussian_.mean(mean(delta_time, state, input));
        gaussian_.diagonal_covariance(covariance(delta_time));
    }

    /* interface API */
    /**
     * \copydoc ProcessModelInterface::condition
     */
    virtual State predict_state(double delta_time,
                                const State& state,
                                const Noise& noise,
                                const Input& input)
    {
        condition(delta_time, state, input);

        return map_standard_normal(noise);
    }

    virtual void parameters(const Scalar& damping,
                            const SecondMoment& noise_covariance)
    {
        damping_ = damping;
        noise_covariance_ = noise_covariance;
    }

    /**
     * This is the same as the state dimension since the state represents the
     * process distribution variate.
     *
     * \return dimension of the state or the process variate
     */
    virtual size_t dimension() const
    {
        return state_dimension();
    }

    /**
     * \copydoc ProcessModelInterface::state_dimension
     */
    virtual size_t state_dimension() const
    {
        return this->standard_variate_dimension();
    }

    /**
     * \copydoc ProcessModelInterface::noise_dimension
     */
    virtual size_t noise_dimension() const
    {
        return this->standard_variate_dimension();
    }

    /**
     * \copydoc ProcessModelInterface::input_dimension
     */
    virtual size_t input_dimension() const
    {
        return this->standard_variate_dimension();
    }

protected:
    /**
     * \param delta_time    \f$\Delta t\f$
     * \param state         \f$x\f$
     * \param input         \f$u\f$
     *
     * \return
     * \f[
     * \mu = e^{-\Delta t d} x + \frac{1-e^{-\Delta t d}}{d}u
     * \f]
     */
    State mean(const Scalar& delta_time,
               const State& state,
               const Input& input)
    {
        // for readability ... the compiler optimizes this out
        const double dt = delta_time;
        const Scalar d = damping_;
        const double exp_ddt = std::exp(-d * dt);

        if(d == 0) return state + delta_time * input;

        State state_expectation = (1.0 - exp_ddt) / d * input + exp_ddt * state;

        /*
         * if the damping_ is too small, the result might be nan, we thus return
         * the limit for damping_ -> 0
         */
        if(!std::isfinite(state_expectation.norm()))
        {
            state_expectation = state + d * input;
        }

        return state_expectation;
    }

    /**
     * \param delta_time    \f$\Delta t\f$
     *
     * \return
     * \f[
     * \Sigma = f \Sigma_{v}
     * \f]
     *
     * with
     *
     * noise covariance matrix \f$\Sigma_{v}\f$ and the factor
     * \f[
     * f = \frac{1 - e^{-2 \Delta t d}}{2 d}
     * \f]
     * while
     * \f$d\f$ being the damping constant.
     */
    SecondMoment covariance(const Scalar& delta_time)
    {
        // for readability ... the compiler optimizes this out
        const double dt = delta_time;
        const Scalar d = damping_;

        if(d == 0) return dt * noise_covariance_;

        Scalar factor = (1.0 - std::exp(-2.0 * d * dt)) / (2.0 * d);

        if(!std::isfinite(factor)) factor = dt;

        return factor * noise_covariance_;
    }

private:
    // conditional
    NoiseGaussian gaussian_;

    // parameters
    Scalar damping_;
    SecondMoment noise_covariance_;
};

}

#endif
<|endoftext|>


<commit_before>#ifndef __CRT_HPP__
#define __CRT_HPP__
#include <stddef.h>

#ifdef __cplusplus
extern "C"
{
#endif
  void *memcpy(void * dst, const void * src, size_t count);
  void *memset(void *dst, int val, size_t count);
  void *memchr(const void * buf, int chr, size_t cnt);
  //char *strstr(const char * str1, const char * str2);
  int memcmp(const void * buf1, const void * buf2, size_t count);
#ifdef __cplusplus
};
#endif

#endif
<commit_msg>update crt.hpp<commit_after>#ifndef __CRT_HPP__
#define __CRT_HPP__
#include <stddef.h>

#ifdef __cplusplus
extern "C"
{
#endif
  void *memcpy(void * dst, const void * src, size_t count);
  void *memset(void *dst, int val, size_t count);
  int memcmp(const void * buf1, const void * buf2, size_t count);
#ifdef __cplusplus
};
#endif

#endif
<|endoftext|>


<commit_before>// This file should document by example usage of the GEOS library.
// It could actually be a live discuss-by-example board for
// architectural design choices.
// 			--strk;
//
// DEBUGGING TIPS:
//  use -D__USE_MALLOC at compile time for gcc 2.91, 2.95, 3.0 and 3.1
//  and GLIBCXX_FORCE_NEW or GLIBCPP_FORCE_NEW at run time with gcc 3.2.2+
//  to force libstdc++ avoid caching memory. This should remove some
//  obscure reports from memory checkers like valgrind.
//
// $Log$
// Revision 1.7  2003/10/29 10:38:43  strk
// Added centroid computation example
//
// Revision 1.6  2003/10/21 16:16:46  strk
// Uncommented point creation lines. Updated comments about segfaults.
//
// Revision 1.5  2003/10/20 17:50:30  strk
// added Union example
//
// Revision 1.4  2003/10/09 11:20:12  strk
// moved Log to a better place
//
// Revision 1.3  2003/10/09 11:19:20  strk
// added convexHull and PrecisionModel
//
//
#include <stdio.h>
#include <io.h>
#include <geom.h>
#include <unload.h>

using namespace geos;

// This object will be used to construct our geometries.
// It might be bypassed by directly call geometry constructors,
// but that would be boring because you'd need to specify
// a PrecisionModel and a SRID everytime: those infos are
// cached inside a GeometryFactory object.
GeometryFactory *global_factory;

// This function will print given geometries in WKT
// format to stdout.
void
wkt_print_geoms(int numgeoms, Geometry **geoms)
{
	// WKT-print given geometries
	WKTWriter *wkt = new WKTWriter();
	for (int i=0; i<numgeoms; i++) {
		//string tmp="test";
		string tmp=wkt->write(geoms[i]);
		cout<<"["<<i<<"] "<<tmp<<endl;
		//cout<<wkt->write(geoms[i])<<endl;
	}
	delete wkt;
}

// This is the simpler geometry you can get: a point.
Point *
create_point(double x, double y)
{
	Point p0;
	Coordinate c;
       	c.x = x;
	c.y = y;
	// the geometry factory will copy coordinate
	Point *p = global_factory->createPoint(c);
	return p;
}

// This function will create a LinearRing
// geometry rapresenting a square with the given origin
// and side
LinearRing *
create_square_linearring(double xoffset, double yoffset, double side)
{
	// We will use a coordinate list to build the linearring
	CoordinateList *cl = new BasicCoordinateList(5);

	// Each coordinate in the list must be created,
	// passed to coordinate list setAt and then deleted.
	// Pretty boring uh ?
	Coordinate *c;
	c = new Coordinate(xoffset, yoffset);
	cl->setAt(*c ,0);
	delete c;
	c = new Coordinate(xoffset+side, yoffset);
	cl->setAt(*c ,1);
	delete c;
	c = new Coordinate(xoffset+side, yoffset+side);
	cl->setAt(*c ,2);
	delete c;
	c = new Coordinate(xoffset, yoffset+side);
	cl->setAt(*c ,3);
	delete c;
	c = new Coordinate(xoffset, yoffset);
	cl->setAt(*c ,4);
	delete c;

	// Now that we have a CoordinateList we can create
	// the linearring.
	LinearRing *lr = (LinearRing*) global_factory->createLinearRing(cl);

	// We don't need our CoordinateList anymore, it has been
	// copied inside the LinearRing object
	delete cl;

	return lr; // our LinearRing
}

// This function will create a Polygon
// geometry rapresenting a square with the given origin
// and side and with a central hole 1/3 sided.
Polygon *
create_square_polygon(double xoffset, double yoffset, double side)
{
	// We need a LinearRing for the polygon shell
	LinearRing *outer = create_square_linearring(xoffset,yoffset,side);

	// And another for the hole
	LinearRing *inner = create_square_linearring(xoffset+(side/3),
			yoffset+(side/3),(side/3));

	// If we need to specify any hole, we do it using
	// a vector of Geometry pointers (I don't know why
	// not LinearRings)
	vector<Geometry *> *holes = new vector<Geometry *>;

	// We add the newly created geometry to the vector
	// of holes.
	holes->push_back(inner);

	// And finally we call the polygon constructor.
	// Both the outer LinearRing and the vector of holes
	// will be referenced by the resulting Polygon object,
	// thus we CANNOT delete them, neither the holes, nor
	// the vector containing their pointers, nor the outer
	// LinearRing. Everything will be deleted at Polygon
	// deletion time (this is inconsistent with LinearRing
	// behaviour... what should we do?).
	Polygon *poly = global_factory->createPolygon(outer, holes);

	return poly;
}

// This function will create a GeoemtryCollection
// containing the two given Geometries.
// Note that given Geometries will be referenced
// by returned object, thus deleted at its destruction
// time.
//
GeometryCollection *
create_simple_collection(Geometry *g1, Geometry *g2)
{
	// We need to construct a <Geometry *> vector
	// to use as argument to the factory function
	vector<Geometry *> *collection = new vector<Geometry *>;

	// Now, we need to make copies of the given args
	// we do it using copy constructor.
	collection->push_back(g1);
	collection->push_back(g2);

	GeometryCollection *ret =
		global_factory->createGeometryCollection(collection);

	// We HAVE to delete the vectors used to store
	// geometry pointers, but created object will
	// delete pointed geometries, weird uh?
	// It seems that somebody else will delete this...
	// must inspect --strk;
	delete collection;

	return ret;
}

// Start reading here
void do_all()
{
	int numgeoms = 5;
	Geometry *geoms[numgeoms];

	// Define a precision model using 0,0 as the reference origin
	// and 2.0 as coordinates scale.
	PrecisionModel *pm = new PrecisionModel(2.0, 0, 0);

	// Initialize global factory with defined PrecisionModel
	// and a SRID of -1 (undefined).
	global_factory = new GeometryFactory(pm, -1);

	// We do not need PrecisionMode object anymore, it has
	// been copied to global_factory private storage
	delete pm;

	/////////////////////////////////////////////
	// BASIC GEOMETRY CREATION
	/////////////////////////////////////////////

	// Read function bodies to see the magic behind them
	geoms[0] = create_square_linearring(0,0,100);
	geoms[1] = create_square_polygon(0,200,300);
	geoms[2] = create_square_polygon(0,250,300);

	// here we write this bad-looking code to copy
	// geometries before putting them in a collection
	// object, since it will take responsability about
	// passed arguments life.
	geoms[3] = create_simple_collection(
			new LinearRing(*((LinearRing *)geoms[0])),
			new Polygon(*((Polygon *)geoms[1])));

	// The simplest geometry: a point !
	geoms[4] = create_point(150, 350);

	// Print all geoms.
	cout<<"--------HERE ARE THE BASE GEOMS ----------"<<endl;
	wkt_print_geoms(numgeoms, geoms);

	/////////////////////////////////////////////
	// CENTROID
	/////////////////////////////////////////////

	// Find centroid of each base geometry
	Geometry *centroid[numgeoms];
	for (int i=0; i<numgeoms; i++) {
		centroid[i] = geoms[i]->getCentroid();
	}

	// Print all convex hulls
	cout<<"------- AND HERE ARE THEIR CENTROIDS -----"<<endl;
	wkt_print_geoms(numgeoms, centroid);

	// Delete the hulls
	for (int i=0; i<numgeoms; i++) {
		delete centroid[i];
	}

	/////////////////////////////////////////////
	// CONVEX HULL
	/////////////////////////////////////////////

	// Make convex hulls of geometries
	Geometry *hulls[numgeoms];
	for (int i=0; i<numgeoms; i++) {
		hulls[i] = geoms[i]->convexHull();
	}

	// Print all convex hulls
	cout<<"--------HERE COMES THE HULLS----------"<<endl;
	wkt_print_geoms(numgeoms, hulls);

	// Delete the hulls
	for (int i=0; i<numgeoms; i++) {
		delete hulls[i];
	}

	/////////////////////////////////////////////
	// UNION
	/////////////////////////////////////////////

	// Make unions of all geoms
	Geometry *unions[numgeoms*numgeoms];
	int numunions=0;
	for (int i=0; i<numgeoms-1; i++) {
		Geometry *g1 = geoms[i];
		for (int j=i+1; j<numgeoms; j++) {
			Geometry *g2 = geoms[j];
			try {
				unions[numunions] = g1->Union(g2);
				numunions++;
			}
			// It's illegal to union a collection ...
			catch (IllegalArgumentException *ill) {
				//cerr <<ill->toString()<<"\n";
				delete ill;
			}
			catch (GEOSException *exc) {
				cerr <<"GEOS Exception: "<<exc->toString()<<"\n";
			}
		}
	}

	// Print all unions
	cout<<"----- AND HERE ARE SOME UNION COMBINATIONS ------"<<endl;
	wkt_print_geoms(numunions, unions);

	// Delete the resulting geoms
	for (int i=0; i<numunions; i++) {
		delete unions[i];
	}

	/////////////////////////////////////////////
	// CLEANUP
	/////////////////////////////////////////////

	// Delete base geometries
	for (int i=0; i<numgeoms; i++) {
		delete geoms[i];
	}

	delete global_factory;
}

main()
{
	try
	{
		do_all();
	}
	// All exception thrown by GEOS are subclasses of this
	// one, so this is a catch-all
	catch (GEOSException *exc)
	{
		cerr <<"GEOS Exception: "<<exc->toString()<<"\n";
		exit(1);
	}
	// and this is a catch-all non standard ;)
	catch (...)
	{
		cerr <<"unknown exception trown!\n";
		exit(1);
	}

	// This is not really needed but to make
	// memory checker like valgrind quiet
	// about static heap-allocated data.
	Unload::Release();
}
<commit_msg>Removed comments about segfaults, made the simple collection creation call cleaner by use of the clone() method.<commit_after>// This file should document by example usage of the GEOS library.
// It could actually be a live discuss-by-example board for
// architectural design choices.
// 			--strk;
//
// DEBUGGING TIPS:
//  use -D__USE_MALLOC at compile time for gcc 2.91, 2.95, 3.0 and 3.1
//  and GLIBCXX_FORCE_NEW or GLIBCPP_FORCE_NEW at run time with gcc 3.2.2+
//  to force libstdc++ avoid caching memory. This should remove some
//  obscure reports from memory checkers like valgrind.
//
// $Log$
// Revision 1.8  2003/11/03 16:09:44  strk
// Removed comments about segfaults, made the simple collection creation call
// cleaner by use of the clone() method.
//
// Revision 1.7  2003/10/29 10:38:43  strk
// Added centroid computation example
//
// Revision 1.6  2003/10/21 16:16:46  strk
// Uncommented point creation lines. Updated comments about segfaults.
//
// Revision 1.5  2003/10/20 17:50:30  strk
// added Union example
//
// Revision 1.4  2003/10/09 11:20:12  strk
// moved Log to a better place
//
// Revision 1.3  2003/10/09 11:19:20  strk
// added convexHull and PrecisionModel
//
//
#include <stdio.h>
#include <io.h>
#include <geom.h>
#include <unload.h>

using namespace geos;

// This object will be used to construct our geometries.
// It might be bypassed by directly call geometry constructors,
// but that would be boring because you'd need to specify
// a PrecisionModel and a SRID everytime: those infos are
// cached inside a GeometryFactory object.
GeometryFactory *global_factory;

// This function will print given geometries in WKT
// format to stdout.
void
wkt_print_geoms(int numgeoms, Geometry **geoms)
{
	// WKT-print given geometries
	WKTWriter *wkt = new WKTWriter();
	for (int i=0; i<numgeoms; i++) {
		//string tmp="test";
		string tmp=wkt->write(geoms[i]);
		cout<<"["<<i<<"] "<<tmp<<endl;
		//cout<<wkt->write(geoms[i])<<endl;
	}
	delete wkt;
}

// This is the simpler geometry you can get: a point.
Point *
create_point(double x, double y)
{
	Point p0;
	Coordinate c;
       	c.x = x;
	c.y = y;
	// the geometry factory will copy coordinate
	Point *p = global_factory->createPoint(c);
	return p;
}

// This function will create a LinearRing
// geometry rapresenting a square with the given origin
// and side
LinearRing *
create_square_linearring(double xoffset, double yoffset, double side)
{
	// We will use a coordinate list to build the linearring
	CoordinateList *cl = new BasicCoordinateList(5);

	// Each coordinate in the list must be created,
	// passed to coordinate list setAt and then deleted.
	// Pretty boring uh ?
	Coordinate *c;
	c = new Coordinate(xoffset, yoffset);
	cl->setAt(*c ,0);
	delete c;
	c = new Coordinate(xoffset+side, yoffset);
	cl->setAt(*c ,1);
	delete c;
	c = new Coordinate(xoffset+side, yoffset+side);
	cl->setAt(*c ,2);
	delete c;
	c = new Coordinate(xoffset, yoffset+side);
	cl->setAt(*c ,3);
	delete c;
	c = new Coordinate(xoffset, yoffset);
	cl->setAt(*c ,4);
	delete c;

	// Now that we have a CoordinateList we can create
	// the linearring.
	LinearRing *lr = (LinearRing*) global_factory->createLinearRing(cl);

	// We don't need our CoordinateList anymore, it has been
	// copied inside the LinearRing object
	delete cl;

	return lr; // our LinearRing
}

// This function will create a Polygon
// geometry rapresenting a square with the given origin
// and side and with a central hole 1/3 sided.
Polygon *
create_square_polygon(double xoffset, double yoffset, double side)
{
	// We need a LinearRing for the polygon shell
	LinearRing *outer = create_square_linearring(xoffset,yoffset,side);

	// And another for the hole
	LinearRing *inner = create_square_linearring(xoffset+(side/3),
			yoffset+(side/3),(side/3));

	// If we need to specify any hole, we do it using
	// a vector of Geometry pointers (I don't know why
	// not LinearRings)
	vector<Geometry *> *holes = new vector<Geometry *>;

	// We add the newly created geometry to the vector
	// of holes.
	holes->push_back(inner);

	// And finally we call the polygon constructor.
	// Both the outer LinearRing and the vector of holes
	// will be referenced by the resulting Polygon object,
	// thus we CANNOT delete them, neither the holes, nor
	// the vector containing their pointers, nor the outer
	// LinearRing. Everything will be deleted at Polygon
	// deletion time (this is inconsistent with LinearRing
	// behaviour... what should we do?).
	Polygon *poly = global_factory->createPolygon(outer, holes);

	return poly;
}

//
// This function will create a GeoemtryCollection
// containing the two given Geometries.
// Note that given Geometries will be referenced
// by returned object, thus deleted at its destruction
// time.
//
GeometryCollection *
create_simple_collection(Geometry *g1, Geometry *g2)
{
	// We need to construct a <Geometry *> vector
	// to use as argument to the factory function
	vector<Geometry *> *collection = new vector<Geometry *>;

	// We fill the vector with given geometries
	collection->push_back(g1);
	collection->push_back(g2);

	GeometryCollection *ret =
		global_factory->createGeometryCollection(collection);

	// We HAVE to delete the vectors used to store
	// geometry pointers, but created object will
	// delete pointed geometries, weird uh?
	delete collection;

	return ret;
}

// Start reading here
void do_all()
{
	int numgeoms = 5;
	Geometry *geoms[numgeoms];

	// Define a precision model using 0,0 as the reference origin
	// and 2.0 as coordinates scale.
	PrecisionModel *pm = new PrecisionModel(2.0, 0, 0);

	// Initialize global factory with defined PrecisionModel
	// and a SRID of -1 (undefined).
	global_factory = new GeometryFactory(pm, -1);

	// We do not need PrecisionMode object anymore, it has
	// been copied to global_factory private storage
	delete pm;

	/////////////////////////////////////////////
	// BASIC GEOMETRY CREATION
	/////////////////////////////////////////////

	// Read function bodies to see the magic behind them
	geoms[0] = create_point(150, 350);
	geoms[1] = create_square_linearring(0,0,100);
	geoms[2] = create_square_polygon(0,200,300);
	geoms[3] = create_square_polygon(0,250,300);

	// We clone geometries before passing them to the
	// geometry collection function.
	geoms[4] = create_simple_collection(
			geoms[0]->clone(), geoms[1]->clone() );

	// Print all geoms.
	cout<<"--------HERE ARE THE BASE GEOMS ----------"<<endl;
	wkt_print_geoms(numgeoms, geoms);

	/////////////////////////////////////////////
	// CENTROID
	/////////////////////////////////////////////

	// Find centroid of each base geometry
	Geometry *centroid[numgeoms];
	for (int i=0; i<numgeoms; i++) {
		centroid[i] = geoms[i]->getCentroid();
	}

	// Print all convex hulls
	cout<<"------- AND HERE ARE THEIR CENTROIDS -----"<<endl;
	wkt_print_geoms(numgeoms, centroid);

	// Delete the hulls
	for (int i=0; i<numgeoms; i++) {
		delete centroid[i];
	}

	/////////////////////////////////////////////
	// CONVEX HULL
	/////////////////////////////////////////////

	// Make convex hulls of geometries
	Geometry *hulls[numgeoms];
	for (int i=0; i<numgeoms; i++) {
		hulls[i] = geoms[i]->convexHull();
	}

	// Print all convex hulls
	cout<<"--------HERE COMES THE HULLS----------"<<endl;
	wkt_print_geoms(numgeoms, hulls);

	// Delete the hulls
	for (int i=0; i<numgeoms; i++) {
		delete hulls[i];
	}

	/////////////////////////////////////////////
	// UNION
	/////////////////////////////////////////////

	// Make unions of all geoms
	Geometry *unions[numgeoms*numgeoms];
	int numunions=0;
	for (int i=0; i<numgeoms-1; i++) {
		Geometry *g1 = geoms[i];
		for (int j=i+1; j<numgeoms; j++) {
			Geometry *g2 = geoms[j];
			try {
				unions[numunions] = g1->Union(g2);
				numunions++;
			}
			// It's illegal to union a collection ...
			catch (IllegalArgumentException *ill) {
				//cerr <<ill->toString()<<"\n";
				delete ill;
			}
			catch (GEOSException *exc) {
				cerr <<"GEOS Exception: "<<exc->toString()<<"\n";
			}
		}
	}

	// Print all unions
	cout<<"----- AND HERE ARE SOME UNION COMBINATIONS ------"<<endl;
	wkt_print_geoms(numunions, unions);

	// Delete the resulting geoms
	for (int i=0; i<numunions; i++) {
		delete unions[i];
	}

	/////////////////////////////////////////////
	// CLEANUP
	/////////////////////////////////////////////

	// Delete base geometries
	for (int i=0; i<numgeoms; i++) {
		delete geoms[i];
	}

	delete global_factory;
}

main()
{
	try
	{
		do_all();
	}
	// All exception thrown by GEOS are subclasses of this
	// one, so this is a catch-all
	catch (GEOSException *exc)
	{
		cerr <<"GEOS Exception: "<<exc->toString()<<"\n";
		exit(1);
	}
	// and this is a catch-all non standard ;)
	catch (...)
	{
		cerr <<"unknown exception trown!\n";
		exit(1);
	}

	// This is not really needed but to make
	// memory checker like valgrind quiet
	// about static heap-allocated data.
	Unload::Release();
}
<|endoftext|>


<commit_before>/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    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.
 */

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
#include "AppTask.h"
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
#include "PigweedLoggerMutex.h"
#include "pigweed/RpcService.h"
#include "pw_sys_io_nrfconnect/init.h"
#include <zephyr/logging/log.h>

#include <zephyr/kernel.h>

LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);

#if defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE
#include "pigweed/rpc_services/Attributes.h"
#endif // defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
#include "pigweed/rpc_services/Button.h"
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE

#if defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE
#include "pigweed/rpc_services/Descriptor.h"
#endif // defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE

#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE
#include "pigweed/rpc_services/Device.h"
#endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE

#if defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE
#include "pigweed/rpc_services/Lighting.h"
#endif // defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE

#if defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE
#include "pigweed/rpc_services/Locking.h"
#endif // defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE

#if defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE
#include "pigweed/rpc_services/OtCli.h"
#endif // defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE

#if defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE
#include "pigweed/rpc_services/Thread.h"
#endif // defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE

#if defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE
#define PW_TRACE_BUFFER_SIZE_BYTES 1024
#include "pw_trace/trace.h"
#include "pw_trace_tokenized/trace_rpc_service_nanopb.h"

// Define trace time for pw_trace
PW_TRACE_TIME_TYPE pw_trace_GetTraceTime()
{
    return (PW_TRACE_TIME_TYPE) chip::System::SystemClock().GetMonotonicMicroseconds64().count();
}
// Microsecond time source
size_t pw_trace_GetTraceTimeTicksPerSecond()
{
    return 1000000;
}

#endif // defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE

namespace chip {
namespace rpc {

#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE
namespace {

void reboot_timer_handler(struct k_timer * dummy)
{
    NVIC_SystemReset();
}
K_TIMER_DEFINE(reboot_timer, reboot_timer_handler, NULL);

} // namespace

class NrfDevice final : public Device
{
public:
    pw::Status Reboot(const pw_protobuf_Empty & request, pw_protobuf_Empty & response) override
    {
        k_timer_start(&reboot_timer, K_SECONDS(1), K_FOREVER);
        return pw::OkStatus();
    }
};
#endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
class NrfButton final : public Button
{
public:
    pw::Status Event(const chip_rpc_ButtonEvent & request, pw_protobuf_Empty & response) override
    {
        GetAppTask().ButtonEventHandler(request.pushed << request.idx /* button_state */, 1 << request.idx /* has_changed */);
        return pw::OkStatus();
    }
};
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE

namespace {

constexpr size_t kRpcTaskSize = 4096;
constexpr int kRpcPriority    = 5;

K_THREAD_STACK_DEFINE(rpc_stack_area, kRpcTaskSize);
struct k_thread rpc_thread_data;

#if defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE
Attributes attributes_service;
#endif // defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
NrfButton button_service;
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE

#if defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE
Descriptor descriptor_service;
#endif // defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE

#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE
NrfDevice device_service;
#endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE

#if defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE
Lighting lighting_service;
#endif // defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE

#if defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE
Locking locking;
#endif // defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE

#if defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE
OtCli ot_cli_service;
#endif // defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE

#if defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE
Thread thread;
#endif // defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE

#if defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE
pw::trace::TraceService trace_service;
#endif // defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE

void RegisterServices(pw::rpc::Server & server)
{
#if defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE
    server.RegisterService(attributes_service);
#endif // defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
    server.RegisterService(button_service);
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE

#if defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE
    server.RegisterService(descriptor_service);
#endif // defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE

#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE
    server.RegisterService(device_service);
#endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE

#if defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE
    server.RegisterService(lighting_service);
#endif // defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE

#if defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE
    server.RegisterService(locking);
#endif // defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE

#if defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE
    server.RegisterService(ot_cli_service);
#endif // defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE

#if defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE
    server.RegisterService(thread);
#endif // defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE

#if defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE
    server.RegisterService(trace_service);
    PW_TRACE_SET_ENABLED(true);
#endif // defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE
}

} // namespace

void RunRpcService(void *, void *, void *)
{
    Start(RegisterServices, &logger_mutex);
}

k_tid_t Init()
{
    pw_sys_io_Init();
    k_tid_t tid = k_thread_create(&rpc_thread_data, rpc_stack_area, K_THREAD_STACK_SIZEOF(rpc_stack_area), RunRpcService, NULL,
                                  NULL, NULL, kRpcPriority, 0, K_NO_WAIT);
    return tid;
}

} // namespace rpc
} // namespace chip
<commit_msg>RPC: Fix NRF Attributes service (#21682)<commit_after>/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    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.
 */

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
#include "AppTask.h"
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
#include "PigweedLoggerMutex.h"
#include "pigweed/RpcService.h"
#include "pw_sys_io_nrfconnect/init.h"
#include <zephyr/logging/log.h>

#include <zephyr/kernel.h>

LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);

#if defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE
#include "pigweed/rpc_services/Attributes.h"
#endif // defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
#include "pigweed/rpc_services/Button.h"
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE

#if defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE
#include "pigweed/rpc_services/Descriptor.h"
#endif // defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE

#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE
#include "pigweed/rpc_services/Device.h"
#endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE

#if defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE
#include "pigweed/rpc_services/Lighting.h"
#endif // defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE

#if defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE
#include "pigweed/rpc_services/Locking.h"
#endif // defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE

#if defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE
#include "pigweed/rpc_services/OtCli.h"
#endif // defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE

#if defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE
#include "pigweed/rpc_services/Thread.h"
#endif // defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE

#if defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE
#define PW_TRACE_BUFFER_SIZE_BYTES 1024
#include "pw_trace/trace.h"
#include "pw_trace_tokenized/trace_rpc_service_nanopb.h"

// Define trace time for pw_trace
PW_TRACE_TIME_TYPE pw_trace_GetTraceTime()
{
    return (PW_TRACE_TIME_TYPE) chip::System::SystemClock().GetMonotonicMicroseconds64().count();
}
// Microsecond time source
size_t pw_trace_GetTraceTimeTicksPerSecond()
{
    return 1000000;
}

#endif // defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE

namespace chip {
namespace rpc {

#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE
namespace {

void reboot_timer_handler(struct k_timer * dummy)
{
    NVIC_SystemReset();
}
K_TIMER_DEFINE(reboot_timer, reboot_timer_handler, NULL);

} // namespace

class NrfDevice final : public Device
{
public:
    pw::Status Reboot(const pw_protobuf_Empty & request, pw_protobuf_Empty & response) override
    {
        k_timer_start(&reboot_timer, K_SECONDS(1), K_FOREVER);
        return pw::OkStatus();
    }
};
#endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
class NrfButton final : public Button
{
public:
    pw::Status Event(const chip_rpc_ButtonEvent & request, pw_protobuf_Empty & response) override
    {
        GetAppTask().ButtonEventHandler(request.pushed << request.idx /* button_state */, 1 << request.idx /* has_changed */);
        return pw::OkStatus();
    }
};
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE

namespace {

constexpr size_t kRpcTaskSize = 5120;
constexpr int kRpcPriority    = 5;

K_THREAD_STACK_DEFINE(rpc_stack_area, kRpcTaskSize);
struct k_thread rpc_thread_data;

#if defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE
Attributes attributes_service;
#endif // defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
NrfButton button_service;
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE

#if defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE
Descriptor descriptor_service;
#endif // defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE

#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE
NrfDevice device_service;
#endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE

#if defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE
Lighting lighting_service;
#endif // defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE

#if defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE
Locking locking;
#endif // defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE

#if defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE
OtCli ot_cli_service;
#endif // defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE

#if defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE
Thread thread;
#endif // defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE

#if defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE
pw::trace::TraceService trace_service;
#endif // defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE

void RegisterServices(pw::rpc::Server & server)
{
#if defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE
    server.RegisterService(attributes_service);
#endif // defined(PW_RPC_ATTRIBUTE_SERVICE) && PW_RPC_ATTRIBUTE_SERVICE

#if defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE
    server.RegisterService(button_service);
#endif // defined(PW_RPC_BUTTON_SERVICE) && PW_RPC_BUTTON_SERVICE

#if defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE
    server.RegisterService(descriptor_service);
#endif // defined(PW_RPC_DESCRIPTOR_SERVICE) && PW_RPC_DESCRIPTOR_SERVICE

#if defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE
    server.RegisterService(device_service);
#endif // defined(PW_RPC_DEVICE_SERVICE) && PW_RPC_DEVICE_SERVICE

#if defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE
    server.RegisterService(lighting_service);
#endif // defined(PW_RPC_LIGHTING_SERVICE) && PW_RPC_LIGHTING_SERVICE

#if defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE
    server.RegisterService(locking);
#endif // defined(PW_RPC_LOCKING_SERVICE) && PW_RPC_LOCKING_SERVICE

#if defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE
    server.RegisterService(ot_cli_service);
#endif // defined(PW_RPC_OTCLI_SERVICE) && PW_RPC_OTCLI_SERVICE

#if defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE
    server.RegisterService(thread);
#endif // defined(PW_RPC_THREAD_SERVICE) && PW_RPC_THREAD_SERVICE

#if defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE
    server.RegisterService(trace_service);
    PW_TRACE_SET_ENABLED(true);
#endif // defined(PW_RPC_TRACING_SERVICE) && PW_RPC_TRACING_SERVICE
}

} // namespace

void RunRpcService(void *, void *, void *)
{
    Start(RegisterServices, &logger_mutex);
}

k_tid_t Init()
{
    pw_sys_io_Init();
    k_tid_t tid = k_thread_create(&rpc_thread_data, rpc_stack_area, K_THREAD_STACK_SIZEOF(rpc_stack_area), RunRpcService, NULL,
                                  NULL, NULL, kRpcPriority, 0, K_NO_WAIT);
    return tid;
}

} // namespace rpc
} // namespace chip
<|endoftext|>


<commit_before>/**
 * Project \
 */

#include "AlgorithmList.h"
#include <QDir>
#include <QPluginLoader>

#define LOGGING_LEVEL_1
#include "log.h"

/**
 * AlgorithmList implementation
 */

/**
 * @param file
 */
AlgorithmList::AlgorithmList(const QString& file) {
    QDir pluginsDir(file);

    for(const QString& fileName : pluginsDir.entryList(QDir::Files))
    {
        QString filePath = pluginsDir.absoluteFilePath(fileName);
        QPluginLoader loader(filePath);
        QObject* plugin = loader.instance();
        if(plugin){
            LOG("loading plugin ", fileName.toStdString(), " ..");
            Algorithm* algo = qobject_cast<Algorithm*>(plugin);
            if(algo){
                LOG("sucessfully loaded plugin");
                mAlgorithmList.push_back(std::unique_ptr<Algorithm>(algo));
            } else {
                LOG("plugin does not implement Algorithm-interface");
            }
        }
    }
}

AlgorithmList::AlgorithmList(AlgorithmList&& a) : mAlgorithmList(std::move(a.mAlgorithmList))
{
}

AlgorithmList& AlgorithmList::operator=(AlgorithmList &&a)
{
    mAlgorithmList = std::move(a.mAlgorithmList);
    return *this;
}

/**
 * @param packet
 * @return QList<Algorithm>
 */
QList<Algorithm*> AlgorithmList::findCompatibleAlgorithms(const DataPacket& packet) {
    return QList<Algorithm*>();
}

/**
 * @return QList<Algorithm>
 */
QList<Algorithm*> AlgorithmList::getAlgorithmList() {
    return QList<Algorithm*>();
}
<commit_msg>Implemented AlgorithmList::getAlgorithmList.<commit_after>/**
 * Project \
 */

#include "AlgorithmList.h"
#include <QDir>
#include <QPluginLoader>

#define LOGGING_LEVEL_1
#include "log.h"

/**
 * AlgorithmList implementation
 */

/**
 * @param file
 */
AlgorithmList::AlgorithmList(const QString& file) {
    QDir pluginsDir(file);

    for(const QString& fileName : pluginsDir.entryList(QDir::Files))
    {
        QString filePath = pluginsDir.absoluteFilePath(fileName);
        QPluginLoader loader(filePath);
        QObject* plugin = loader.instance();
        if(plugin){
            LOG("loading plugin ", fileName.toStdString(), " ..");
            Algorithm* algo = qobject_cast<Algorithm*>(plugin);
            if(algo){
                LOG("sucessfully loaded plugin");
                mAlgorithmList.push_back(std::unique_ptr<Algorithm>(algo));
            } else {
                LOG("plugin does not implement Algorithm-interface");
            }
        }
    }
}

AlgorithmList::AlgorithmList(AlgorithmList&& a) : mAlgorithmList(std::move(a.mAlgorithmList))
{
}

AlgorithmList& AlgorithmList::operator=(AlgorithmList &&a)
{
    mAlgorithmList = std::move(a.mAlgorithmList);
    return *this;
}

/**
 * @param packet
 * @return QList<Algorithm>
 */
QList<Algorithm*> AlgorithmList::findCompatibleAlgorithms(const DataPacket& packet) {
    return QList<Algorithm*>();
}

/**
 * @return QList<Algorithm>
 */
QList<Algorithm*> AlgorithmList::getAlgorithmList() {
    QList<Algorithm*> algos;
    for(const auto& uniqueAlgo : mAlgorithmList){
        algos.push_back(uniqueAlgo.get());
    }
    return algos;
}
<|endoftext|>


<commit_before>// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "StdAfx.h"
#include "..\MainApp.h"
#include "Utilities.h"
#include <Rpc.h>

DWORD CountSetBits(ULONG_PTR bitMask)
{
    DWORD LSHIFT = sizeof(ULONG_PTR) * 8 - 1;
    DWORD bitSetCount = 0;
    ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;
    DWORD i;

    for (i = 0; i <= LSHIFT; ++i)
    {
        bitSetCount += ((bitMask & bitTest) ? 1 : 0);
        bitTest /= 2;
    }

    return bitSetCount;
}

int GetLogicalProcessorInformation(LogicalProcessorInformation* info)
{
    LPFN_GLPI glpi;
    BOOL done = FALSE;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
    DWORD returnLength = 0;
    DWORD byteOffset = 0;
    PCACHE_DESCRIPTOR Cache;

    glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
    if (NULL == glpi)
    {
#ifdef _DEBUG
        _tprintf(_T("\nGetLogicalProcessorInformation is not supported.\n"));
#endif
        return (1);
    }

    while (!done)
    {
        DWORD rc = glpi(buffer, &returnLength);
        if (FALSE == rc)
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                if (buffer)
                    free(buffer);

                buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);
                if (NULL == buffer)
                {
#ifdef _DEBUG
                    _tprintf(_T("\nError: Allocation failure\n"));
#endif
                    return (2);
                }
            }
            else
            {
#ifdef _DEBUG
                _tprintf(_T("\nError %d\n"), GetLastError());
#endif
                return (3);
            }
        }
        else
        {
            done = TRUE;
        }
    }

    ptr = buffer;

    while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
    {
        switch (ptr->Relationship)
        {
        case RelationNumaNode:
            // Non-NUMA systems report a single record of this type.
            info->numaNodeCount++;
            break;
        case RelationProcessorCore:
            info->processorCoreCount++;
            // A hyperthreaded core supplies more than one logical processor.
            info->logicalProcessorCount += CountSetBits(ptr->ProcessorMask);
            break;
        case RelationCache:
            // Cache data is in ptr->Cache, one CACHE_DESCRIPTOR structure for each cache.
            Cache = &ptr->Cache;
            if (Cache->Level == 1)
            {
                info->processorL1CacheCount++;
            }
            else if (Cache->Level == 2)
            {
                info->processorL2CacheCount++;
            }
            else if (Cache->Level == 3)
            {
                info->processorL3CacheCount++;
            }
            break;
        case RelationProcessorPackage:
            // Logical processors share a physical package.
            info->processorPackageCount++;
            break;
        default:
#ifdef _DEBUG
            _tprintf(_T("\nError: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value.\n"));
#endif
            break;
        }
        byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
        ptr++;
    }

#ifdef _DEBUG
    _tprintf(_T("\nGetLogicalProcessorInformation results:\n"));
    _tprintf(_T("Number of NUMA nodes: %d\n"), info->numaNodeCount);
    _tprintf(_T("Number of physical processor packages: %d\n"), info->processorPackageCount);
    _tprintf(_T("Number of processor cores: %d\n"), info->processorCoreCount);
    _tprintf(_T("Number of logical processors: %d\n"), info->logicalProcessorCount);
    _tprintf(_T("Number of processor L1/L2/L3 caches: %d/%d/%d\n"),
        info->processorL1CacheCount,
        info->processorL2CacheCount,
        info->processorL3CacheCount);
#endif

    free(buffer);
    return (0);
}

void ShutdownWindows()
{
    HANDLE m_hToken;
    if (::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &m_hToken))
    {
        LUID m_Luid;
        if (::LookupPrivilegeValue(NULL, _T("SeShutdownPrivilege"), &m_Luid))
        {
            TOKEN_PRIVILEGES tp;
            tp.PrivilegeCount = 1;
            tp.Privileges[0].Luid = m_Luid;
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            ::AdjustTokenPrivileges(m_hToken, FALSE, &tp, 0, NULL, NULL);
        }
        ::CloseHandle(m_hToken);
    }
    ::ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF | EWX_FORCEIFHUNG, 0);
    ::PostQuitMessage(0);
}

void LaunchAndWait(LPCTSTR file, LPCTSTR params, BOOL bWait)
{
    // leave sei.lpVerb uninitialized for default action
    SHELLEXECUTEINFO sei;
    ::ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
    sei.cbSize = sizeof(SHELLEXECUTEINFO);
    sei.fMask = SEE_MASK_NOCLOSEPROCESS;
    sei.nShow = SW_SHOWNORMAL;
    sei.lpFile = file;
    sei.lpParameters = params;
    ::ShellExecuteEx(&sei);
    if (bWait == TRUE)
        ::WaitForSingleObject(sei.hProcess, INFINITE);
    ::CloseHandle(sei.hProcess);
}

void SetComboBoxHeight(HWND hDlg, int nComboBoxID, int nSizeLimit)
{
    HWND hComboxBox = ::GetDlgItem(hDlg, nComboBoxID);
    if (hComboxBox != NULL)
        ::SendMessage(hComboxBox, CB_SETMINVISIBLE, (WPARAM)nSizeLimit, 0);
}

UINT GetFileNameInternal(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax)
{
    LPTSTR lpszTemp = ::PathFindFileName(lpszPathName);
    if (lpszTitle == NULL)
        return lstrlen(lpszTemp) + 1;
    lstrcpyn(lpszTitle, lpszTemp, nMax);
    return(0);
}

CString GetFileName(CString szFilePath)
{
    CString strResult;
    ::GetFileNameInternal(szFilePath, strResult.GetBuffer(_MAX_FNAME), _MAX_FNAME);
    strResult.ReleaseBuffer();
    return strResult;
}

CString GetFilePath(CString szFilePath)
{
    CString strResult = szFilePath;
    CString szFileName = ::GetFileName(szFilePath);
    int nPathLength = szFilePath.GetLength() - szFileName.GetLength();
    strResult.Truncate(nPathLength);
    return strResult;
}

CString GetOnlyFileName(CString szFilePath)
{
    CString szFileName = ::GetFileName(szFilePath);
    szFileName.TrimRight(::GetFileExtension(szFilePath));
    szFileName.TrimRight(_T("."));
    return szFileName;
}

CString GetFileExtension(CString szFilePath)
{
    CString szExt = ::PathFindExtension(szFilePath);
    szExt.Remove('.');
    return szExt;
}

ULONGLONG GetFileSize64(HANDLE hFile)
{
    ULARGE_INTEGER liSize;
    liSize.LowPart = ::GetFileSize(hFile, &liSize.HighPart);
    if (liSize.LowPart == (DWORD)-1)
    {
        if (::GetLastError() != NO_ERROR)
            return(0);
    }
    return liSize.QuadPart;
}

CString GetExeFilePath()
{
    TCHAR szExeFilePath[MAX_PATH + 1] = _T("");
    DWORD dwRet = ::GetModuleFileName(::GetModuleHandle(NULL), szExeFilePath, MAX_PATH);
    if (dwRet > 0)
    {
        CString szTempBuff1;
        CString szTempBuff2;
        szTempBuff1.Format(_T("%s"), szExeFilePath);
        szTempBuff2 = ::GetFileName(szTempBuff1);
        szTempBuff1.TrimRight(szTempBuff2);
        return szTempBuff1;
    }
    return NULL;
}

void GetFullPathName(CString &szFilePath)
{
    TCHAR szFullPath[MAX_PATH + 2] = _T("");
    LPTSTR pszFilePos = NULL;
    ::GetFullPathName(szFilePath, MAX_PATH + 1, szFullPath, &pszFilePos);
    szFilePath = szFullPath;
}

BOOL DirectoryExists(LPCTSTR szPath)
{
    if (_taccess_s(szPath, 0) == 0)
    {
        struct _stat status;
        _tstat(szPath, &status);
        return (status.st_mode & S_IFDIR) != 0;
    }
    return FALSE;
}

BOOL MakeFullPath(CString szPath)
{
    if (szPath[szPath.GetLength() - 1] != '\\')
        szPath = szPath + _T("\\");

    CString szTmpDir = szPath.Left(2);
    _tchdir(szTmpDir);

    int nStart = 3;
    int nEnd = 0;
    while (TRUE)
    {
        nEnd = szPath.Find('\\', nStart);
        if (nEnd == -1)
            return TRUE;

        CString szNextDir = szPath.Mid(nStart, nEnd - nStart);
        CString szCurDir = szTmpDir + _T("\\") + szNextDir;
        if (_tchdir(szCurDir) != 0)
        {
            _tchdir(szTmpDir);
            if (_tmkdir(szNextDir) != 0)
                return FALSE;
        }

        szTmpDir += _T("\\") + szNextDir;
        nStart = nEnd + 1;
    }
    return FALSE;
}

bool FileExists(CString szPath)
{
    WIN32_FIND_DATA w32FileData;
    ZeroMemory(&w32FileData, sizeof(WIN32_FIND_DATA));
    HANDLE hFind = ::FindFirstFile(szPath, &w32FileData);
    bool bInvalidHandle = hFind == INVALID_HANDLE_VALUE;
    ::FindClose(hFind);
    return bInvalidHandle == false;
}

CString GenerateUuidString()
{
    CString strKey;
    UUID uuid;
    if (UuidCreate(&uuid) == RPC_S_OK)
    {
        RPC_WSTR szUuid;
        if (UuidToString(&uuid, &szUuid) == RPC_S_OK)
        {
            strKey = (LPTSTR)szUuid;
            strKey.MakeUpper();
            RpcStringFree(&szUuid);
        }
    }
    return strKey;
}

CString ReplaceNoCase(LPCTSTR instr, LPCTSTR oldstr, LPCTSTR newstr)
{
    CString output(instr);
    CString inputLower(instr);
    CString oldLower(oldstr);
    inputLower.MakeLower();
    oldLower.MakeLower();
    int pos = 0;
    for (;;)
    {
        pos = inputLower.Find(oldLower, pos);
        if (pos == -1)
            break;
        inputLower.Delete(pos, lstrlen(oldstr));
        inputLower.Insert(pos, newstr);
        output.Delete(pos, lstrlen(oldstr));
        output.Insert(pos, newstr);
        pos += lstrlen(newstr);
    }
    return output;
}

int FindNoCase(LPCTSTR pszString, LPCTSTR pszSearch)
{
    int lenString = lstrlen(pszString);
    int lenSearch = lstrlen(pszSearch);
    if (lenSearch == 0 || lenSearch > lenString)
        return -1;
    for (int i = 0; i < lenString - lenSearch + 1; ++i)
    {
        if (_tcsncicmp(&pszString[i], pszSearch, lenSearch) == 0)
            return i;
    }
    return -1;
}
<commit_msg>Removed include<commit_after>// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "StdAfx.h"
#include "Utilities.h"
#include <Rpc.h>

DWORD CountSetBits(ULONG_PTR bitMask)
{
    DWORD LSHIFT = sizeof(ULONG_PTR) * 8 - 1;
    DWORD bitSetCount = 0;
    ULONG_PTR bitTest = (ULONG_PTR)1 << LSHIFT;
    DWORD i;

    for (i = 0; i <= LSHIFT; ++i)
    {
        bitSetCount += ((bitMask & bitTest) ? 1 : 0);
        bitTest /= 2;
    }

    return bitSetCount;
}

int GetLogicalProcessorInformation(LogicalProcessorInformation* info)
{
    LPFN_GLPI glpi;
    BOOL done = FALSE;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
    DWORD returnLength = 0;
    DWORD byteOffset = 0;
    PCACHE_DESCRIPTOR Cache;

    glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
    if (NULL == glpi)
    {
#ifdef _DEBUG
        _tprintf(_T("\nGetLogicalProcessorInformation is not supported.\n"));
#endif
        return (1);
    }

    while (!done)
    {
        DWORD rc = glpi(buffer, &returnLength);
        if (FALSE == rc)
        {
            if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
            {
                if (buffer)
                    free(buffer);

                buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);
                if (NULL == buffer)
                {
#ifdef _DEBUG
                    _tprintf(_T("\nError: Allocation failure\n"));
#endif
                    return (2);
                }
            }
            else
            {
#ifdef _DEBUG
                _tprintf(_T("\nError %d\n"), GetLastError());
#endif
                return (3);
            }
        }
        else
        {
            done = TRUE;
        }
    }

    ptr = buffer;

    while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength)
    {
        switch (ptr->Relationship)
        {
        case RelationNumaNode:
            // Non-NUMA systems report a single record of this type.
            info->numaNodeCount++;
            break;
        case RelationProcessorCore:
            info->processorCoreCount++;
            // A hyperthreaded core supplies more than one logical processor.
            info->logicalProcessorCount += CountSetBits(ptr->ProcessorMask);
            break;
        case RelationCache:
            // Cache data is in ptr->Cache, one CACHE_DESCRIPTOR structure for each cache.
            Cache = &ptr->Cache;
            if (Cache->Level == 1)
            {
                info->processorL1CacheCount++;
            }
            else if (Cache->Level == 2)
            {
                info->processorL2CacheCount++;
            }
            else if (Cache->Level == 3)
            {
                info->processorL3CacheCount++;
            }
            break;
        case RelationProcessorPackage:
            // Logical processors share a physical package.
            info->processorPackageCount++;
            break;
        default:
#ifdef _DEBUG
            _tprintf(_T("\nError: Unsupported LOGICAL_PROCESSOR_RELATIONSHIP value.\n"));
#endif
            break;
        }
        byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
        ptr++;
    }

#ifdef _DEBUG
    _tprintf(_T("\nGetLogicalProcessorInformation results:\n"));
    _tprintf(_T("Number of NUMA nodes: %d\n"), info->numaNodeCount);
    _tprintf(_T("Number of physical processor packages: %d\n"), info->processorPackageCount);
    _tprintf(_T("Number of processor cores: %d\n"), info->processorCoreCount);
    _tprintf(_T("Number of logical processors: %d\n"), info->logicalProcessorCount);
    _tprintf(_T("Number of processor L1/L2/L3 caches: %d/%d/%d\n"),
        info->processorL1CacheCount,
        info->processorL2CacheCount,
        info->processorL3CacheCount);
#endif

    free(buffer);
    return (0);
}

void ShutdownWindows()
{
    HANDLE m_hToken;
    if (::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &m_hToken))
    {
        LUID m_Luid;
        if (::LookupPrivilegeValue(NULL, _T("SeShutdownPrivilege"), &m_Luid))
        {
            TOKEN_PRIVILEGES tp;
            tp.PrivilegeCount = 1;
            tp.Privileges[0].Luid = m_Luid;
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            ::AdjustTokenPrivileges(m_hToken, FALSE, &tp, 0, NULL, NULL);
        }
        ::CloseHandle(m_hToken);
    }
    ::ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF | EWX_FORCEIFHUNG, 0);
    ::PostQuitMessage(0);
}

void LaunchAndWait(LPCTSTR file, LPCTSTR params, BOOL bWait)
{
    // leave sei.lpVerb uninitialized for default action
    SHELLEXECUTEINFO sei;
    ::ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
    sei.cbSize = sizeof(SHELLEXECUTEINFO);
    sei.fMask = SEE_MASK_NOCLOSEPROCESS;
    sei.nShow = SW_SHOWNORMAL;
    sei.lpFile = file;
    sei.lpParameters = params;
    ::ShellExecuteEx(&sei);
    if (bWait == TRUE)
        ::WaitForSingleObject(sei.hProcess, INFINITE);
    ::CloseHandle(sei.hProcess);
}

void SetComboBoxHeight(HWND hDlg, int nComboBoxID, int nSizeLimit)
{
    HWND hComboxBox = ::GetDlgItem(hDlg, nComboBoxID);
    if (hComboxBox != NULL)
        ::SendMessage(hComboxBox, CB_SETMINVISIBLE, (WPARAM)nSizeLimit, 0);
}

UINT GetFileNameInternal(LPCTSTR lpszPathName, LPTSTR lpszTitle, UINT nMax)
{
    LPTSTR lpszTemp = ::PathFindFileName(lpszPathName);
    if (lpszTitle == NULL)
        return lstrlen(lpszTemp) + 1;
    lstrcpyn(lpszTitle, lpszTemp, nMax);
    return(0);
}

CString GetFileName(CString szFilePath)
{
    CString strResult;
    ::GetFileNameInternal(szFilePath, strResult.GetBuffer(_MAX_FNAME), _MAX_FNAME);
    strResult.ReleaseBuffer();
    return strResult;
}

CString GetFilePath(CString szFilePath)
{
    CString strResult = szFilePath;
    CString szFileName = ::GetFileName(szFilePath);
    int nPathLength = szFilePath.GetLength() - szFileName.GetLength();
    strResult.Truncate(nPathLength);
    return strResult;
}

CString GetOnlyFileName(CString szFilePath)
{
    CString szFileName = ::GetFileName(szFilePath);
    szFileName.TrimRight(::GetFileExtension(szFilePath));
    szFileName.TrimRight(_T("."));
    return szFileName;
}

CString GetFileExtension(CString szFilePath)
{
    CString szExt = ::PathFindExtension(szFilePath);
    szExt.Remove('.');
    return szExt;
}

ULONGLONG GetFileSize64(HANDLE hFile)
{
    ULARGE_INTEGER liSize;
    liSize.LowPart = ::GetFileSize(hFile, &liSize.HighPart);
    if (liSize.LowPart == (DWORD)-1)
    {
        if (::GetLastError() != NO_ERROR)
            return(0);
    }
    return liSize.QuadPart;
}

CString GetExeFilePath()
{
    TCHAR szExeFilePath[MAX_PATH + 1] = _T("");
    DWORD dwRet = ::GetModuleFileName(::GetModuleHandle(NULL), szExeFilePath, MAX_PATH);
    if (dwRet > 0)
    {
        CString szTempBuff1;
        CString szTempBuff2;
        szTempBuff1.Format(_T("%s"), szExeFilePath);
        szTempBuff2 = ::GetFileName(szTempBuff1);
        szTempBuff1.TrimRight(szTempBuff2);
        return szTempBuff1;
    }
    return NULL;
}

void GetFullPathName(CString &szFilePath)
{
    TCHAR szFullPath[MAX_PATH + 2] = _T("");
    LPTSTR pszFilePos = NULL;
    ::GetFullPathName(szFilePath, MAX_PATH + 1, szFullPath, &pszFilePos);
    szFilePath = szFullPath;
}

BOOL DirectoryExists(LPCTSTR szPath)
{
    if (_taccess_s(szPath, 0) == 0)
    {
        struct _stat status;
        _tstat(szPath, &status);
        return (status.st_mode & S_IFDIR) != 0;
    }
    return FALSE;
}

BOOL MakeFullPath(CString szPath)
{
    if (szPath[szPath.GetLength() - 1] != '\\')
        szPath = szPath + _T("\\");

    CString szTmpDir = szPath.Left(2);
    _tchdir(szTmpDir);

    int nStart = 3;
    int nEnd = 0;
    while (TRUE)
    {
        nEnd = szPath.Find('\\', nStart);
        if (nEnd == -1)
            return TRUE;

        CString szNextDir = szPath.Mid(nStart, nEnd - nStart);
        CString szCurDir = szTmpDir + _T("\\") + szNextDir;
        if (_tchdir(szCurDir) != 0)
        {
            _tchdir(szTmpDir);
            if (_tmkdir(szNextDir) != 0)
                return FALSE;
        }

        szTmpDir += _T("\\") + szNextDir;
        nStart = nEnd + 1;
    }
    return FALSE;
}

bool FileExists(CString szPath)
{
    WIN32_FIND_DATA w32FileData;
    ZeroMemory(&w32FileData, sizeof(WIN32_FIND_DATA));
    HANDLE hFind = ::FindFirstFile(szPath, &w32FileData);
    bool bInvalidHandle = hFind == INVALID_HANDLE_VALUE;
    ::FindClose(hFind);
    return bInvalidHandle == false;
}

CString GenerateUuidString()
{
    CString strKey;
    UUID uuid;
    if (UuidCreate(&uuid) == RPC_S_OK)
    {
        RPC_WSTR szUuid;
        if (UuidToString(&uuid, &szUuid) == RPC_S_OK)
        {
            strKey = (LPTSTR)szUuid;
            strKey.MakeUpper();
            RpcStringFree(&szUuid);
        }
    }
    return strKey;
}

CString ReplaceNoCase(LPCTSTR instr, LPCTSTR oldstr, LPCTSTR newstr)
{
    CString output(instr);
    CString inputLower(instr);
    CString oldLower(oldstr);
    inputLower.MakeLower();
    oldLower.MakeLower();
    int pos = 0;
    for (;;)
    {
        pos = inputLower.Find(oldLower, pos);
        if (pos == -1)
            break;
        inputLower.Delete(pos, lstrlen(oldstr));
        inputLower.Insert(pos, newstr);
        output.Delete(pos, lstrlen(oldstr));
        output.Insert(pos, newstr);
        pos += lstrlen(newstr);
    }
    return output;
}

int FindNoCase(LPCTSTR pszString, LPCTSTR pszSearch)
{
    int lenString = lstrlen(pszString);
    int lenSearch = lstrlen(pszSearch);
    if (lenSearch == 0 || lenSearch > lenString)
        return -1;
    for (int i = 0; i < lenString - lenSearch + 1; ++i)
    {
        if (_tcsncicmp(&pszString[i], pszSearch, lenSearch) == 0)
            return i;
    }
    return -1;
}
<|endoftext|>


<commit_before>// Copyright © 2017-2018 Dmitriy Khaustov
//
// 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.
//
// Author: Dmitriy Khaustov aka xDimon
// Contacts: khaustov.dm@gmail.com
// File created on: 2017.06.02

// NopeException.hpp

#pragma once

class NopeException final: public std::exception
{
};
<commit_msg>Little fix import<commit_after>// Copyright © 2017-2018 Dmitriy Khaustov
//
// 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.
//
// Author: Dmitriy Khaustov aka xDimon
// Contacts: khaustov.dm@gmail.com
// File created on: 2017.06.02

// NopeException.hpp

#pragma once

#include <exception>

class NopeException final: public std::exception
{
};
<|endoftext|>


<commit_before>/* Copyright 2016 Google Inc. 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.
==============================================================================*/
#include "tensorflow/core/util/memmapped_file_system.h"

#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/util/memmapped_file_system.pb.h"

namespace tensorflow {

namespace {

uint64 DecodeUint64LittleEndian(const uint8* buffer) {
  uint64 result = 0;
  for (int i = 0; i < static_cast<int>(sizeof(uint64)); ++i) {
    result |= buffer[i] << (8 * i);
  }
  return result;
}

}  // namespace

namespace {

class ReadOnlyMemoryRegionFromMemmapped : public ReadOnlyMemoryRegion {
 public:
  ReadOnlyMemoryRegionFromMemmapped(const void* data, uint64 length)
      : data_(data), length_(length) {}
  ~ReadOnlyMemoryRegionFromMemmapped() override = default;
  const void* data() override { return data_; }
  uint64 length() override { return length_; }

 private:
  const void* const data_;
  const uint64 length_;
  // intentionally copyable
};

class RandomAccessFileFromMemmapped : public RandomAccessFile {
 public:
  RandomAccessFileFromMemmapped(const void* data, uint64 length)
      : data_(data), length_(length) {}

  ~RandomAccessFileFromMemmapped() override = default;

  Status Read(uint64 offset, size_t to_read, StringPiece* result,
              char* scratch) const override {
    if (offset >= length_) {
      result->set(scratch, 0);
      return Status(error::OUT_OF_RANGE, "Read after file end");
    }
    const uint64 region_left =
        std::min(length_ - offset, static_cast<uint64>(to_read));
    result->set(reinterpret_cast<const uint8*>(data_) + offset, region_left);
    return (region_left == to_read)
               ? Status::OK()
               : Status(error::OUT_OF_RANGE, "Read less bytes than requested");
  }

 private:
  const void* const data_;
  const uint64 length_;
  // intentionally copyable
};

}  // namespace

MemmappedFileSystem::MemmappedFileSystem() {}

bool MemmappedFileSystem::FileExists(const string& fname) {
  if (!mapped_memory_) {
    return false;
  }
  const auto dir_element = directory_.find(fname);
  return dir_element != directory_.end();
}

Status MemmappedFileSystem::NewRandomAccessFile(const string& filename,
                                                RandomAccessFile** result) {
  if (!mapped_memory_) {
    return errors::FailedPrecondition("MemmappedEnv is not initialized");
  }
  const auto dir_element = directory_.find(filename);
  if (dir_element == directory_.end()) {
    return errors::NotFound("Region ", filename, " is not found");
  }
  *result = new RandomAccessFileFromMemmapped(
      GetMemoryWithOffset(dir_element->second.offset),
      dir_element->second.length);
  return Status::OK();
}

Status MemmappedFileSystem::NewReadOnlyMemoryRegionFromFile(
    const string& filename, ReadOnlyMemoryRegion** result) {
  if (!mapped_memory_) {
    return errors::FailedPrecondition("MemmappedEnv is not initialized");
  }
  const auto dir_element = directory_.find(filename);
  if (dir_element == directory_.end()) {
    return errors::NotFound("Region ", filename, " is not found");
  }
  *result = new ReadOnlyMemoryRegionFromMemmapped(
      GetMemoryWithOffset(dir_element->second.offset),
      dir_element->second.length);
  return Status::OK();
}

Status MemmappedFileSystem::GetFileSize(const string& filename, uint64* size) {
  if (!mapped_memory_) {
    return errors::FailedPrecondition("MemmappedEnv is not initialized");
  }
  const auto dir_element = directory_.find(filename);
  if (dir_element == directory_.end()) {
    return errors::NotFound("Region ", filename, " is not found");
  }
  *size = dir_element->second.length;
  return Status::OK();
}

Status MemmappedFileSystem::NewWritableFile(const string& filename,
                                            WritableFile** wf) {
  return errors::Unimplemented("memmapped format doesn't support writing");
}

Status MemmappedFileSystem::NewAppendableFile(const string& filename,
                                              WritableFile** result) {
  return errors::Unimplemented("memmapped format doesn't support writing");
}

Status MemmappedFileSystem::GetChildren(const string& filename,
                                        std::vector<string>* strings) {
  return errors::Unimplemented("memmapped format doesn't support GetChildren");
}

Status MemmappedFileSystem::DeleteFile(const string& filename) {
  return errors::Unimplemented("memmapped format doesn't support DeleteFile");
}

Status MemmappedFileSystem::CreateDir(const string& dirname) {
  return errors::Unimplemented("memmapped format doesn't support CreateDir");
}

Status MemmappedFileSystem::DeleteDir(const string& dirname) {
  return errors::Unimplemented("memmapped format doesn't support DeleteDir");
}

Status MemmappedFileSystem::RenameFile(const string& filename_from,
                                       const string& filename_to) {
  return errors::Unimplemented("memmapped format doesn't support RenameFile");
}

const void* MemmappedFileSystem::GetMemoryWithOffset(uint64 offset) const {
  return reinterpret_cast<const uint8*>(mapped_memory_->data()) + offset;
}

constexpr char MemmappedFileSystem::kMemmappedPackagePrefix[];
constexpr char MemmappedFileSystem::kMemmappedPackageDefaultGraphDef[];

Status MemmappedFileSystem::InitializeFromFile(Env* env,
                                               const string& filename) {
  ReadOnlyMemoryRegion* region;
  TF_RETURN_IF_ERROR(env->NewReadOnlyMemoryRegionFromFile(filename, &region));
  mapped_memory_.reset(region);
  directory_.clear();
  if (mapped_memory_->length() <= sizeof(uint64)) {
    return errors::DataLoss("Corrupted memmapped model file: ", filename,
                            " Invalid package size");
  }
  const auto memory_start =
      reinterpret_cast<const uint8*>(mapped_memory_->data());
  const uint64 directory_offset = DecodeUint64LittleEndian(
      memory_start + mapped_memory_->length() - sizeof(uint64));
  if (directory_offset > mapped_memory_->length() - sizeof(uint64)) {
    return errors::DataLoss("Corrupted memmapped model file: ", filename,
                            " Invalid directory offset");
  }
  MemmappedFileSystemDirectory proto_directory;
  if (!ParseProtoUnlimited(
          &proto_directory, memory_start + directory_offset,
          mapped_memory_->length() - directory_offset - sizeof(uint64))) {
    return errors::DataLoss("Corrupted memmapped model file: ", filename,
                            " Can't parse its internal directory");
  }

  // Iterating in reverse order to get lengths of elements;
  uint64 prev_element_offset = directory_offset;
  for (auto element_iter = proto_directory.element().rbegin();
       element_iter != proto_directory.element().rend(); ++element_iter) {
    // Check that the element offset is in the right range.
    if (element_iter->offset() >= prev_element_offset) {
      return errors::DataLoss("Corrupted memmapped model file: ", filename,
                              " Invalid offset of internal component");
    }
    if (!directory_
             .insert(std::make_pair(
                 element_iter->name(),
                 FileRegion(element_iter->offset(),
                            prev_element_offset - element_iter->offset())))
             .second) {
      return errors::DataLoss("Corrupted memmapped model file: ", filename,
                              " Duplicate name of internal component ",
                              element_iter->name());
    }
    prev_element_offset = element_iter->offset();
  }
  return Status::OK();
}

bool MemmappedFileSystem::IsMemmappedPackageFilename(const string& filename) {
  return StringPiece(filename).starts_with(kMemmappedPackagePrefix);
}

namespace {
bool IsValidRegionChar(char c) {
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
         (c >= '0' && c <= '9') || c == '_' || c == '.';
}
}  // namespace

bool MemmappedFileSystem::IsWellFormedMemmappedPackageFilename(
    const string& filename) {
  if (!IsMemmappedPackageFilename(filename)) {
    return false;
  }
  for (char c :
       filename.substr(strlen(kMemmappedPackagePrefix),
                       filename.length() - strlen(kMemmappedPackagePrefix))) {
    if (!IsValidRegionChar(c)) {
      return false;
    }
  }
  return true;
}

MemmappedEnv::MemmappedEnv(Env* env) : EnvWrapper(env) {}

Status MemmappedEnv::GetFileSystemForFile(const string& fname,
                                          FileSystem** result) {
  if (MemmappedFileSystem::IsMemmappedPackageFilename(fname)) {
    if (!memmapped_file_system_) {
      return errors::FailedPrecondition(
          "MemmappedEnv is not initialized from a file.");
    }
    *result = memmapped_file_system_.get();
    return Status::OK();
  }
  return EnvWrapper::GetFileSystemForFile(fname, result);
}

Status MemmappedEnv::GetRegisteredFileSystemSchemes(
    std::vector<string>* schemes) {
  const auto status = EnvWrapper::GetRegisteredFileSystemSchemes(schemes);
  if (status.ok()) {
    schemes->emplace_back(MemmappedFileSystem::kMemmappedPackagePrefix);
  }
  return status;
}

Status MemmappedEnv::InitializeFromFile(const string& package_filename) {
  std::unique_ptr<MemmappedFileSystem> file_system_ptr(new MemmappedFileSystem);
  const auto status =
      file_system_ptr->InitializeFromFile(target(), package_filename);
  if (status.ok()) {
    memmapped_file_system_ = std::move(file_system_ptr);
  }
  return status;
}

}  // namespace tensorflow
<commit_msg>Fixed asan test for memmapped file system Change: 120261367<commit_after>/* Copyright 2016 Google Inc. 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.
==============================================================================*/
#include "tensorflow/core/util/memmapped_file_system.h"

#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/util/memmapped_file_system.pb.h"

namespace tensorflow {

namespace {

uint64 DecodeUint64LittleEndian(const uint8* buffer) {
  uint64 result = 0;
  for (int i = 0; i < static_cast<int>(sizeof(uint64)); ++i) {
    result |= static_cast<uint64>(buffer[i]) << (8 * i);
  }
  return result;
}

}  // namespace

namespace {

class ReadOnlyMemoryRegionFromMemmapped : public ReadOnlyMemoryRegion {
 public:
  ReadOnlyMemoryRegionFromMemmapped(const void* data, uint64 length)
      : data_(data), length_(length) {}
  ~ReadOnlyMemoryRegionFromMemmapped() override = default;
  const void* data() override { return data_; }
  uint64 length() override { return length_; }

 private:
  const void* const data_;
  const uint64 length_;
  // intentionally copyable
};

class RandomAccessFileFromMemmapped : public RandomAccessFile {
 public:
  RandomAccessFileFromMemmapped(const void* data, uint64 length)
      : data_(data), length_(length) {}

  ~RandomAccessFileFromMemmapped() override = default;

  Status Read(uint64 offset, size_t to_read, StringPiece* result,
              char* scratch) const override {
    if (offset >= length_) {
      result->set(scratch, 0);
      return Status(error::OUT_OF_RANGE, "Read after file end");
    }
    const uint64 region_left =
        std::min(length_ - offset, static_cast<uint64>(to_read));
    result->set(reinterpret_cast<const uint8*>(data_) + offset, region_left);
    return (region_left == to_read)
               ? Status::OK()
               : Status(error::OUT_OF_RANGE, "Read less bytes than requested");
  }

 private:
  const void* const data_;
  const uint64 length_;
  // intentionally copyable
};

}  // namespace

MemmappedFileSystem::MemmappedFileSystem() {}

bool MemmappedFileSystem::FileExists(const string& fname) {
  if (!mapped_memory_) {
    return false;
  }
  const auto dir_element = directory_.find(fname);
  return dir_element != directory_.end();
}

Status MemmappedFileSystem::NewRandomAccessFile(const string& filename,
                                                RandomAccessFile** result) {
  if (!mapped_memory_) {
    return errors::FailedPrecondition("MemmappedEnv is not initialized");
  }
  const auto dir_element = directory_.find(filename);
  if (dir_element == directory_.end()) {
    return errors::NotFound("Region ", filename, " is not found");
  }
  *result = new RandomAccessFileFromMemmapped(
      GetMemoryWithOffset(dir_element->second.offset),
      dir_element->second.length);
  return Status::OK();
}

Status MemmappedFileSystem::NewReadOnlyMemoryRegionFromFile(
    const string& filename, ReadOnlyMemoryRegion** result) {
  if (!mapped_memory_) {
    return errors::FailedPrecondition("MemmappedEnv is not initialized");
  }
  const auto dir_element = directory_.find(filename);
  if (dir_element == directory_.end()) {
    return errors::NotFound("Region ", filename, " is not found");
  }
  *result = new ReadOnlyMemoryRegionFromMemmapped(
      GetMemoryWithOffset(dir_element->second.offset),
      dir_element->second.length);
  return Status::OK();
}

Status MemmappedFileSystem::GetFileSize(const string& filename, uint64* size) {
  if (!mapped_memory_) {
    return errors::FailedPrecondition("MemmappedEnv is not initialized");
  }
  const auto dir_element = directory_.find(filename);
  if (dir_element == directory_.end()) {
    return errors::NotFound("Region ", filename, " is not found");
  }
  *size = dir_element->second.length;
  return Status::OK();
}

Status MemmappedFileSystem::NewWritableFile(const string& filename,
                                            WritableFile** wf) {
  return errors::Unimplemented("memmapped format doesn't support writing");
}

Status MemmappedFileSystem::NewAppendableFile(const string& filename,
                                              WritableFile** result) {
  return errors::Unimplemented("memmapped format doesn't support writing");
}

Status MemmappedFileSystem::GetChildren(const string& filename,
                                        std::vector<string>* strings) {
  return errors::Unimplemented("memmapped format doesn't support GetChildren");
}

Status MemmappedFileSystem::DeleteFile(const string& filename) {
  return errors::Unimplemented("memmapped format doesn't support DeleteFile");
}

Status MemmappedFileSystem::CreateDir(const string& dirname) {
  return errors::Unimplemented("memmapped format doesn't support CreateDir");
}

Status MemmappedFileSystem::DeleteDir(const string& dirname) {
  return errors::Unimplemented("memmapped format doesn't support DeleteDir");
}

Status MemmappedFileSystem::RenameFile(const string& filename_from,
                                       const string& filename_to) {
  return errors::Unimplemented("memmapped format doesn't support RenameFile");
}

const void* MemmappedFileSystem::GetMemoryWithOffset(uint64 offset) const {
  return reinterpret_cast<const uint8*>(mapped_memory_->data()) + offset;
}

constexpr char MemmappedFileSystem::kMemmappedPackagePrefix[];
constexpr char MemmappedFileSystem::kMemmappedPackageDefaultGraphDef[];

Status MemmappedFileSystem::InitializeFromFile(Env* env,
                                               const string& filename) {
  ReadOnlyMemoryRegion* region;
  TF_RETURN_IF_ERROR(env->NewReadOnlyMemoryRegionFromFile(filename, &region));
  mapped_memory_.reset(region);
  directory_.clear();
  if (mapped_memory_->length() <= sizeof(uint64)) {
    return errors::DataLoss("Corrupted memmapped model file: ", filename,
                            " Invalid package size");
  }
  const auto memory_start =
      reinterpret_cast<const uint8*>(mapped_memory_->data());
  const uint64 directory_offset = DecodeUint64LittleEndian(
      memory_start + mapped_memory_->length() - sizeof(uint64));
  if (directory_offset > mapped_memory_->length() - sizeof(uint64)) {
    return errors::DataLoss("Corrupted memmapped model file: ", filename,
                            " Invalid directory offset");
  }
  MemmappedFileSystemDirectory proto_directory;
  if (!ParseProtoUnlimited(
          &proto_directory, memory_start + directory_offset,
          mapped_memory_->length() - directory_offset - sizeof(uint64))) {
    return errors::DataLoss("Corrupted memmapped model file: ", filename,
                            " Can't parse its internal directory");
  }

  // Iterating in reverse order to get lengths of elements;
  uint64 prev_element_offset = directory_offset;
  for (auto element_iter = proto_directory.element().rbegin();
       element_iter != proto_directory.element().rend(); ++element_iter) {
    // Check that the element offset is in the right range.
    if (element_iter->offset() >= prev_element_offset) {
      return errors::DataLoss("Corrupted memmapped model file: ", filename,
                              " Invalid offset of internal component");
    }
    if (!directory_
             .insert(std::make_pair(
                 element_iter->name(),
                 FileRegion(element_iter->offset(),
                            prev_element_offset - element_iter->offset())))
             .second) {
      return errors::DataLoss("Corrupted memmapped model file: ", filename,
                              " Duplicate name of internal component ",
                              element_iter->name());
    }
    prev_element_offset = element_iter->offset();
  }
  return Status::OK();
}

bool MemmappedFileSystem::IsMemmappedPackageFilename(const string& filename) {
  return StringPiece(filename).starts_with(kMemmappedPackagePrefix);
}

namespace {
bool IsValidRegionChar(char c) {
  return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
         (c >= '0' && c <= '9') || c == '_' || c == '.';
}
}  // namespace

bool MemmappedFileSystem::IsWellFormedMemmappedPackageFilename(
    const string& filename) {
  if (!IsMemmappedPackageFilename(filename)) {
    return false;
  }
  for (char c :
       filename.substr(strlen(kMemmappedPackagePrefix),
                       filename.length() - strlen(kMemmappedPackagePrefix))) {
    if (!IsValidRegionChar(c)) {
      return false;
    }
  }
  return true;
}

MemmappedEnv::MemmappedEnv(Env* env) : EnvWrapper(env) {}

Status MemmappedEnv::GetFileSystemForFile(const string& fname,
                                          FileSystem** result) {
  if (MemmappedFileSystem::IsMemmappedPackageFilename(fname)) {
    if (!memmapped_file_system_) {
      return errors::FailedPrecondition(
          "MemmappedEnv is not initialized from a file.");
    }
    *result = memmapped_file_system_.get();
    return Status::OK();
  }
  return EnvWrapper::GetFileSystemForFile(fname, result);
}

Status MemmappedEnv::GetRegisteredFileSystemSchemes(
    std::vector<string>* schemes) {
  const auto status = EnvWrapper::GetRegisteredFileSystemSchemes(schemes);
  if (status.ok()) {
    schemes->emplace_back(MemmappedFileSystem::kMemmappedPackagePrefix);
  }
  return status;
}

Status MemmappedEnv::InitializeFromFile(const string& package_filename) {
  std::unique_ptr<MemmappedFileSystem> file_system_ptr(new MemmappedFileSystem);
  const auto status =
      file_system_ptr->InitializeFromFile(target(), package_filename);
  if (status.ok()) {
    memmapped_file_system_ = std::move(file_system_ptr);
  }
  return status;
}

}  // namespace tensorflow
<|endoftext|>