<commit_before>// *****************************************************************************
//
// Copyright (c) 2014, Southwest Research Institute® (SwRI®)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Southwest Research Institute® (SwRI®) 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *****************************************************************************

#include <stdint.h>

#include <swri_geometry_util/intersection.h>

#define HAVE_INT64_T_64  # Prevents conflict with OpenCV typedef of int64
#include <geos/geom/CoordinateArraySequence.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Polygon.h>
#undef HAVE_INT64_T_64

namespace swri_geometry_util
{
  bool LineIntersection(
      const cv::Vec2d& p1,
      const cv::Vec2d& p2,
      const cv::Vec2d& p3,
      const cv::Vec2d& p4,
      cv::Vec2d& c)
  {
    double d = (p1[0] - p2[0]) * (p3[1] - p4[1]) - (p1[1] - p2[1]) * (p3[0] - p4[0]);
    if (d == 0)
    {
      return false;
    }

    double n_a = (p1[0] * p2[1] - p1[1] * p2[0]) * (p3[0] - p4[0]) - (p1[0] - p2[0]) * (p3[0] * p4[1] - p3[1] * p4[0]);
    double n_b = (p1[0] * p2[1] - p1[1] * p2[0]) * (p3[1] - p4[1]) - (p1[1] - p2[1]) * (p3[0] * p4[1] - p3[1] * p4[0]);

    c[0] = n_a / d;
    c[1] = n_b / d;

    return true;
  }

  bool LineSegmentIntersection(
      const cv::Vec2d& p1,
      const cv::Vec2d& p2,
      const cv::Vec2d& p3,
      const cv::Vec2d& p4,
      cv::Vec2d& c)
  {
    // See: "Intersection of two lines in three-space"
    //      by Ronald Goldman from Graphics Gems

    // Handle case of singe points.
    if (p1 == p2)
    {
      if (PointOnLineSegment(p1, p3, p4))
      {
        c = p1;
        return true;
      }

      return false;
    }
    else if (p3 == p4)
    {
      if (PointOnLineSegment(p3, p1, p2))
      {
        c = p3;
        return true;
      }

      return false;
    }

    cv::Point2d p(p1);
    cv::Point2d r(p2 - p1);
    cv::Point2d q(p3);
    cv::Point2d s(p4 - p3);
    cv::Point2d qp(q - p);

    double rs = r.cross(s);
    if (std::fabs(rs) > std::numeric_limits<float>::epsilon())
    {
      // Explicitly divide components since cv::Point doesn't support division
      // in indigo.
      double t = qp.cross(cv::Point2d(s.x / rs, s.y / rs));
      double u = (qp * -1).cross(cv::Point2d(r.x / -rs, r.y / -rs));

      if (u >= 0 && t >= 0 && u <= 1.0 && t <= 1.0)
      {
        // The lines intersect within the line segments.
        c = p + t * r;
        return true;
      }
      else
      {
        // The lines intersect, but outside the line segments.
        return false;
      }
    }
    else if (std::fabs(qp.cross(r)) > std::numeric_limits<float>::epsilon())
    {
      // The lines are parellel and non-intersecting.
      return false;
    }
    else
    {
      // The lines are parellel and coincident.
      double rlen = r.dot(r);
      cv::Point2d unit_r(r.x / rlen, r.y / rlen);
      double t0 = qp.dot(unit_r);
      double t1 = t0 + s.dot(unit_r);

      if (t0 > t1)
      {
        std::swap(t0, t1);
      }

      if (t0 <= 1.0 && t1 >= 0.0)
      {
        // The line segments overlap.

        double t = std::max(0.0, t0);
        c = p + t * r;
        return true;
      }

      // The line segments don't overlap.
      return false;
    }
  }

  bool PointOnLineSegment(
      const cv::Vec2d& p1,
      const cv::Vec2d& p2,
      const cv::Vec2d& p3)
  {
    // Check if the points are collinear.
    if (((p2[0] - p1[0]) * (p3[1] - p1[0])) - ((p3[0] - p1[0]) * (p2[1] - p1[1])) > std::numeric_limits<float>::epsilon())
    {
      return false;
    }

    if (p2[0] != p3[0])
    {
      return (p1[0] <= p3[0] && p2[0] <= p1[0]) || (p1[0] <= p2[0] && p3[0] <= p1[0]);
    }
    else
    {
      return (p1[1] <= p3[1] && p2[1] <= p1[1]) || (p1[1] <= p2[1] && p3[1] <= p1[1]);
    }
  }

  bool PolygonsIntersect(
      const std::vector<cv::Vec2d>& a,
      const std::vector<cv::Vec2d>& b)
  {
    // Create GEOS polygon from vertices in vector a.
    geos::geom::CoordinateSequence* a_coords = new geos::geom::CoordinateArraySequence();
    for (size_t i = 0; i < a.size(); i++)
    {
      a_coords->add(geos::geom::Coordinate(a[i][0], a[i][1]));
    }
    a_coords->add(a_coords->front());

    geos::geom::LinearRing* a_ring = geos::geom::GeometryFactory::getDefaultInstance()->createLinearRing(a_coords);
    geos::geom::Polygon* a_polygon = geos::geom::GeometryFactory::getDefaultInstance()->createPolygon(a_ring, 0);
    a_polygon->normalize();

    // Create GEOS polygon from vertices in vector b.
    geos::geom::CoordinateSequence* b_coords = new geos::geom::CoordinateArraySequence();
    for (size_t i = 0; i < b.size(); i++)
    {
      b_coords->add(geos::geom::Coordinate(b[i][0], b[i][1]));
    }
    b_coords->add(b_coords->front());

    geos::geom::LinearRing* b_ring = geos::geom::GeometryFactory::getDefaultInstance()->createLinearRing(b_coords);
    geos::geom::Polygon* b_polygon = geos::geom::GeometryFactory::getDefaultInstance()->createPolygon(b_ring, 0);
    b_polygon->normalize();

    bool intersects =  a_polygon->intersects(b_polygon);

    // Free polygon objects.
    delete a_polygon;
    delete b_polygon;

    return intersects;
  }

  double PolygonIntersectionArea(
      const std::vector<cv::Vec2d>& a,
      const std::vector<cv::Vec2d>& b)
  {
    if (a.size() < 3 || b.size() < 3)
    {
      return 0;
    }

    double area = 0;
    // Create GEOS polygon from vertices in vector a.
    geos::geom::CoordinateSequence* a_coords = new geos::geom::CoordinateArraySequence();
    for (size_t i = 0; i < a.size(); i++)
    {
      a_coords->add(geos::geom::Coordinate(a[i][0], a[i][1]));
    }
    a_coords->add(a_coords->front());

    geos::geom::LinearRing* a_ring = geos::geom::GeometryFactory::getDefaultInstance()->createLinearRing(a_coords);
    geos::geom::Polygon* a_polygon = geos::geom::GeometryFactory::getDefaultInstance()->createPolygon(a_ring, 0);
    a_polygon->normalize();

    // Create GEOS polygon from vertices in vector b.
    geos::geom::CoordinateSequence* b_coords = new geos::geom::CoordinateArraySequence();
    for (size_t i = 0; i < b.size(); i++)
    {
      b_coords->add(geos::geom::Coordinate(b[i][0], b[i][1]));
    }
    b_coords->add(b_coords->front());

    geos::geom::LinearRing* b_ring = geos::geom::GeometryFactory::getDefaultInstance()->createLinearRing(b_coords);
    geos::geom::Polygon* b_polygon = geos::geom::GeometryFactory::getDefaultInstance()->createPolygon(b_ring, 0);
    b_polygon->normalize();

    if (a_polygon->intersects(b_polygon))
    {
      area = a_polygon->intersection(b_polygon)->getArea();
    }

    // Free polygon objects.
    delete a_polygon;
    delete b_polygon;

    return area;
  }
}
<commit_msg>Catch exceptions when computing area<commit_after>// *****************************************************************************
//
// Copyright (c) 2014, Southwest Research Institute® (SwRI®)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Southwest Research Institute® (SwRI®) 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// *****************************************************************************

#include <stdint.h>

#include <swri_geometry_util/intersection.h>

#define HAVE_INT64_T_64  # Prevents conflict with OpenCV typedef of int64
#include <geos/geom/CoordinateArraySequence.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Polygon.h>
#include <geos/util/TopologyException.h>
#undef HAVE_INT64_T_64

namespace swri_geometry_util
{
  bool LineIntersection(
      const cv::Vec2d& p1,
      const cv::Vec2d& p2,
      const cv::Vec2d& p3,
      const cv::Vec2d& p4,
      cv::Vec2d& c)
  {
    double d = (p1[0] - p2[0]) * (p3[1] - p4[1]) - (p1[1] - p2[1]) * (p3[0] - p4[0]);
    if (d == 0)
    {
      return false;
    }

    double n_a = (p1[0] * p2[1] - p1[1] * p2[0]) * (p3[0] - p4[0]) - (p1[0] - p2[0]) * (p3[0] * p4[1] - p3[1] * p4[0]);
    double n_b = (p1[0] * p2[1] - p1[1] * p2[0]) * (p3[1] - p4[1]) - (p1[1] - p2[1]) * (p3[0] * p4[1] - p3[1] * p4[0]);

    c[0] = n_a / d;
    c[1] = n_b / d;

    return true;
  }

  bool LineSegmentIntersection(
      const cv::Vec2d& p1,
      const cv::Vec2d& p2,
      const cv::Vec2d& p3,
      const cv::Vec2d& p4,
      cv::Vec2d& c)
  {
    // See: "Intersection of two lines in three-space"
    //      by Ronald Goldman from Graphics Gems

    // Handle case of singe points.
    if (p1 == p2)
    {
      if (PointOnLineSegment(p1, p3, p4))
      {
        c = p1;
        return true;
      }

      return false;
    }
    else if (p3 == p4)
    {
      if (PointOnLineSegment(p3, p1, p2))
      {
        c = p3;
        return true;
      }

      return false;
    }

    cv::Point2d p(p1);
    cv::Point2d r(p2 - p1);
    cv::Point2d q(p3);
    cv::Point2d s(p4 - p3);
    cv::Point2d qp(q - p);

    double rs = r.cross(s);
    if (std::fabs(rs) > std::numeric_limits<float>::epsilon())
    {
      // Explicitly divide components since cv::Point doesn't support division
      // in indigo.
      double t = qp.cross(cv::Point2d(s.x / rs, s.y / rs));
      double u = (qp * -1).cross(cv::Point2d(r.x / -rs, r.y / -rs));

      if (u >= 0 && t >= 0 && u <= 1.0 && t <= 1.0)
      {
        // The lines intersect within the line segments.
        c = p + t * r;
        return true;
      }
      else
      {
        // The lines intersect, but outside the line segments.
        return false;
      }
    }
    else if (std::fabs(qp.cross(r)) > std::numeric_limits<float>::epsilon())
    {
      // The lines are parellel and non-intersecting.
      return false;
    }
    else
    {
      // The lines are parellel and coincident.
      double rlen = r.dot(r);
      cv::Point2d unit_r(r.x / rlen, r.y / rlen);
      double t0 = qp.dot(unit_r);
      double t1 = t0 + s.dot(unit_r);

      if (t0 > t1)
      {
        std::swap(t0, t1);
      }

      if (t0 <= 1.0 && t1 >= 0.0)
      {
        // The line segments overlap.

        double t = std::max(0.0, t0);
        c = p + t * r;
        return true;
      }

      // The line segments don't overlap.
      return false;
    }
  }

  bool PointOnLineSegment(
      const cv::Vec2d& p1,
      const cv::Vec2d& p2,
      const cv::Vec2d& p3)
  {
    // Check if the points are collinear.
    if (((p2[0] - p1[0]) * (p3[1] - p1[0])) - ((p3[0] - p1[0]) * (p2[1] - p1[1])) > std::numeric_limits<float>::epsilon())
    {
      return false;
    }

    if (p2[0] != p3[0])
    {
      return (p1[0] <= p3[0] && p2[0] <= p1[0]) || (p1[0] <= p2[0] && p3[0] <= p1[0]);
    }
    else
    {
      return (p1[1] <= p3[1] && p2[1] <= p1[1]) || (p1[1] <= p2[1] && p3[1] <= p1[1]);
    }
  }

  bool PolygonsIntersect(
      const std::vector<cv::Vec2d>& a,
      const std::vector<cv::Vec2d>& b)
  {
    // Create GEOS polygon from vertices in vector a.
    geos::geom::CoordinateSequence* a_coords = new geos::geom::CoordinateArraySequence();
    for (size_t i = 0; i < a.size(); i++)
    {
      a_coords->add(geos::geom::Coordinate(a[i][0], a[i][1]));
    }
    a_coords->add(a_coords->front());

    geos::geom::LinearRing* a_ring = geos::geom::GeometryFactory::getDefaultInstance()->createLinearRing(a_coords);
    geos::geom::Polygon* a_polygon = geos::geom::GeometryFactory::getDefaultInstance()->createPolygon(a_ring, 0);
    a_polygon->normalize();

    // Create GEOS polygon from vertices in vector b.
    geos::geom::CoordinateSequence* b_coords = new geos::geom::CoordinateArraySequence();
    for (size_t i = 0; i < b.size(); i++)
    {
      b_coords->add(geos::geom::Coordinate(b[i][0], b[i][1]));
    }
    b_coords->add(b_coords->front());

    geos::geom::LinearRing* b_ring = geos::geom::GeometryFactory::getDefaultInstance()->createLinearRing(b_coords);
    geos::geom::Polygon* b_polygon = geos::geom::GeometryFactory::getDefaultInstance()->createPolygon(b_ring, 0);
    b_polygon->normalize();

    bool intersects =  a_polygon->intersects(b_polygon);

    // Free polygon objects.
    delete a_polygon;
    delete b_polygon;

    return intersects;
  }

  double PolygonIntersectionArea(
      const std::vector<cv::Vec2d>& a,
      const std::vector<cv::Vec2d>& b)
  {
    if (a.size() < 3 || b.size() < 3)
    {
      return 0;
    }

    double area = 0;
    // Create GEOS polygon from vertices in vector a.
    geos::geom::CoordinateSequence* a_coords = new geos::geom::CoordinateArraySequence();
    for (size_t i = 0; i < a.size(); i++)
    {
      a_coords->add(geos::geom::Coordinate(a[i][0], a[i][1]));
    }
    a_coords->add(a_coords->front());

    geos::geom::LinearRing* a_ring = geos::geom::GeometryFactory::getDefaultInstance()->createLinearRing(a_coords);
    geos::geom::Polygon* a_polygon = geos::geom::GeometryFactory::getDefaultInstance()->createPolygon(a_ring, 0);
    a_polygon->normalize();

    // Create GEOS polygon from vertices in vector b.
    geos::geom::CoordinateSequence* b_coords = new geos::geom::CoordinateArraySequence();
    for (size_t i = 0; i < b.size(); i++)
    {
      b_coords->add(geos::geom::Coordinate(b[i][0], b[i][1]));
    }
    b_coords->add(b_coords->front());

    geos::geom::LinearRing* b_ring = geos::geom::GeometryFactory::getDefaultInstance()->createLinearRing(b_coords);
    geos::geom::Polygon* b_polygon = geos::geom::GeometryFactory::getDefaultInstance()->createPolygon(b_ring, 0);
    b_polygon->normalize();

    try
    {
        if (a_polygon->intersects(b_polygon))
        {
          area = a_polygon->intersection(b_polygon)->getArea();
        }
    }
    catch (const geos::util::TopologyException& e)
    {
        // TODO Fix this
    }

    // Free polygon objects.
    delete a_polygon;
    delete b_polygon;

    return area;
  }
}
<|endoftext|>


<commit_before>/***********************************************************************
 test_manip.cpp - Tests the quoting and escaping manipulators.

 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

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

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

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

#include <mysql++.h>

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

template <class T>
static bool
is_quoted(const std::string& s, T orig_str, size_t orig_len)
{
	return (s.length() == (orig_len + 2)) &&
			(s.at(0) == '\'') &&
			(s.at(orig_len + 1) == '\'') &&
			(s.compare(1, orig_len, orig_str) == 0);
}

// Stringish types should be quoted when inserted into Query when an
// explicit quote manipulator is used.
template <class T>
static bool
test_explicit_query_quote(mysqlpp::Query& q, T test, size_t len)
{
	q.reset();
	q << mysqlpp::quote << test;
	if (is_quoted(q.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in Query failed: " << q.str() << std::endl;
		return false;
	}
}

// Stringish types should be quoted when inserted into an ostream when
// an explicit quote manipulator is used.
template <class T>
static bool
test_explicit_ostream_quote(T test, size_t len)
{
	std::ostringstream outs;
	outs << mysqlpp::quote << test;
	if (is_quoted(outs.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in ostream failed: " << outs.str() << std::endl;
		return false;
	}
}

// Stringish types should be implicitly quoted when inserted into Query
template <class T>
static bool
test_implicit_query_quote(mysqlpp::Query& q, T test, size_t len)
{
	q.reset();
	q << test;
	if (is_quoted(q.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Implicit quote of " << typeid(test).name() <<
				" in Query failed: " << q.str() << std::endl;
		return false;
	}
}

// Stringish types should NOT be implicitly quoted when inserted into
// non-Query ostreams
template <class T>
static bool
fail_implicit_ostream_quote(T test, size_t len)
{
	std::ostringstream outs;
	outs << mysqlpp::quote << test;
	if (!is_quoted(outs.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Erroneously quoted " << typeid(test).name() <<
				" in non-Query ostream: " << outs.str() << std::endl;
		return false;
	}
}

// Run all tests above for the given type
template <class T>
static bool
test(mysqlpp::Query& q, T test, size_t len)
{
	return test_explicit_query_quote(q, test, len) &&
			test_explicit_ostream_quote(test, len) &&
			test_implicit_query_quote(q, test, len) &&
			!fail_implicit_ostream_quote(test, len);
}

int
main()
{
	mysqlpp::Connection c;
	mysqlpp::Query q(&c);

	char s[] = "Doodle me, James, doodle me!";
	const size_t len = strlen(s);

	int failures = 0;
	failures += test(q, s, len) == false;
	failures += test(q, (char*)s, len) == false;
	failures += test(q, (const char*)s, len) == false;
	failures += test(q, std::string(s), len) == false;
	failures += test(q, mysqlpp::ColData(s), len) == false;
	return failures;
}

<commit_msg>test_manip now passes all tests.  Earlier notion that these tests should fail and the library needs changing was wrong.  There are tests we could write that should fail and which will pass when the proposed manipulator changes are made, but these are not those.<commit_after>/***********************************************************************
 test_manip.cpp - Tests the quoting and escaping manipulators.

 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

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

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

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

#include <mysql++.h>

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

template <class T>
static bool
is_quoted(const std::string& s, T orig_str, size_t orig_len)
{
	return (s.length() == (orig_len + 2)) &&
			(s.at(0) == '\'') &&
			(s.at(orig_len + 1) == '\'') &&
			(s.compare(1, orig_len, orig_str) == 0);
}

// Stringish types should be quoted when inserted into Query when an
// explicit quote manipulator is used.
template <class T>
static bool
test_explicit_query_quote(mysqlpp::Query& q, T test, size_t len)
{
	q.reset();
	q << mysqlpp::quote << test;
	if (is_quoted(q.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in Query failed: " << q.str() << std::endl;
		return false;
	}
}

// Stringish types should be quoted when inserted into an ostream when
// an explicit quote manipulator is used.
template <class T>
static bool
test_explicit_ostream_quote(T test, size_t len)
{
	std::ostringstream outs;
	outs << mysqlpp::quote << test;
	if (is_quoted(outs.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in ostream failed: " << outs.str() << std::endl;
		return false;
	}
}

// The only stringish type that should be implicitly quoted when
// inserted into Query is ColData, and not always then; we don't know
// enough about anything else to make good automated choices.
template <class T>
static bool
test_implicit_query_quote(mysqlpp::Query& q, T test, size_t len)
{
	q.reset();
	q << test;
	if (is_quoted(q.str(), test, len) ||
			(typeid(test) != typeid(mysqlpp::ColData))) {
		return true;
	}
	else {
		std::cerr << "Implicit quote of " << typeid(test).name() <<
				" in Query failed: " << q.str() << std::endl;
		return false;
	}
}

// Stringish types should NOT be implicitly quoted when inserted into
// non-Query ostreams
template <class T>
static bool
fail_implicit_ostream_quote(T test, size_t len)
{
	std::ostringstream outs;
	outs << mysqlpp::quote << test;
	if (!is_quoted(outs.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Erroneously quoted " << typeid(test).name() <<
				" in non-Query ostream: " << outs.str() << std::endl;
		return false;
	}
}

// Run all tests above for the given type
template <class T>
static bool
test(mysqlpp::Query& q, T test, size_t len)
{
	return test_explicit_query_quote(q, test, len) &&
			test_explicit_ostream_quote(test, len) &&
			test_implicit_query_quote(q, test, len) &&
			!fail_implicit_ostream_quote(test, len);
}

int
main()
{
	mysqlpp::Connection c;
	mysqlpp::Query q(&c);

	char s[] = "Doodle me, James, doodle me!";
	const size_t len = strlen(s);

	int failures = 0;
	failures += test(q, s, len) == false;
	failures += test(q, (char*)s, len) == false;
	failures += test(q, (const char*)s, len) == false;
	failures += test(q, std::string(s), len) == false;
	failures += test(q, mysqlpp::ColData(s), len) == false;
	return failures;
}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 Marc Boris Duerner, Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#ifdef HAVE_ACCEPT4
#include <sys/types.h>
#include <sys/socket.h>
#endif

#include "tcpsocketimpl.h"
#include "tcpserverimpl.h"
#include "cxxtools/net/tcpserver.h"
#include "cxxtools/net/tcpsocket.h"
#include "cxxtools/systemerror.h"
#include "cxxtools/ioerror.h"
#include "cxxtools/log.h"
#include "config.h"
#include "error.h"
#include <cerrno>
#include <cstring>
#include <cassert>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

log_define("cxxtools.net.tcpsocket.impl")

namespace cxxtools
{

namespace net
{

void formatIp(const sockaddr_storage& addr, std::string& str)
{
#ifdef HAVE_INET_NTOP
    const sockaddr_in* sa = reinterpret_cast<const sockaddr_in*>(&addr);
    char strbuf[INET6_ADDRSTRLEN + 1];
    const char* p = inet_ntop(sa->sin_family, &sa->sin_addr, strbuf, sizeof(strbuf));
    str = (p == 0 ? "-" : strbuf);
#else
    static cxxtools::Mutex monitor;
    cxxtools::MutexLock lock(monitor);

    const sockaddr_in* sa = reinterpret_cast<const sockaddr_in*>(&addr);
    const char* p = inet_ntoa(sa->sin_addr);
    if (p)
        str = p;
    else
        str.clear();
#endif
}

TcpSocketImpl::TcpSocketImpl(TcpSocket& socket)
: IODeviceImpl(socket)
, _socket(socket)
, _isConnected(false)
{
}

TcpSocketImpl::~TcpSocketImpl()
{
    assert(_pfd == 0);
}

void TcpSocketImpl::close()
{
    log_debug("close socket " << _fd);
    IODeviceImpl::close();
    _isConnected = false;
}

std::string TcpSocketImpl::getSockAddr() const
{
    struct sockaddr_storage addr;

    socklen_t slen = sizeof(addr);
    if (::getsockname(fd(), reinterpret_cast<struct sockaddr*>(&addr), &slen) < 0)
        throw SystemError("getsockname");

    std::string ret;
    formatIp(addr, ret);
    return ret;
}

std::string TcpSocketImpl::getPeerAddr() const
{
    std::string ret;
    formatIp(_peeraddr, ret);
    return ret;
}

void TcpSocketImpl::connect(const AddrInfo& addrInfo)
{
    log_debug("connect");
    this->beginConnect(addrInfo);
    this->endConnect();
}

int TcpSocketImpl::checkConnect()
{
    log_trace("checkConnect");

    int sockerr;
    socklen_t optlen = sizeof(sockerr);

    // check for socket error
    if( ::getsockopt(this->fd(), SOL_SOCKET, SO_ERROR, &sockerr, &optlen) != 0 )
    {
        // getsockopt failed
        int e = errno;
        close();
        throw SystemError(e, "getsockopt");
    }

    if (sockerr == 0)
    {
        log_debug("connected successfully to " << getPeerAddr());
        _isConnected = true;
    }

    return sockerr;
}

void TcpSocketImpl::checkPendingError()
{
    if (_connectResult.second)
    {
        std::pair<int, const char*> p = _connectResult;
        _connectResult = std::pair<int, const char*>(0, 0);

        if (p.first)
        {
            throw IOError(getErrnoString(p.first, p.second).c_str());
        }
        else
        {
            throw IOError("invalid address information");
        }
    }
}

std::pair<int, const char*> TcpSocketImpl::tryConnect()
{
    log_trace("tryConnect");

    assert(_fd == -1);

    if (_addrInfoPtr == _addrInfo.impl()->end())
    {
        log_debug("no more address informations");
        return std::pair<int, const char*>(0, "invalid address information");
    }

    while (true)
    {
        int fd;
        while (true)
        {
            log_debug("create socket");
            fd = ::socket(_addrInfoPtr->ai_family, SOCK_STREAM, 0);
            if (fd >= 0)
                break;

            if (++_addrInfoPtr == _addrInfo.impl()->end())
                return std::pair<int, const char*>(errno, "socket");
        }

        IODeviceImpl::open(fd, true, false);

        std::memmove(&_peeraddr, _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen);

        log_debug("created socket " << _fd << " max: " << FD_SETSIZE);

        if( ::connect(this->fd(), _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen) == 0 )
        {
            _isConnected = true;
            log_debug("connected successfully to " << getPeerAddr());
            break;
        }

        if (errno == EINPROGRESS)
        {
            log_debug("connect in progress");
            break;
        }

        close();
        if (++_addrInfoPtr == _addrInfo.impl()->end())
            return std::pair<int, const char*>(errno, "connect");
    }

    return std::pair<int, const char*>(0, 0);
}

bool TcpSocketImpl::beginConnect(const AddrInfo& addrInfo)
{
    log_trace("begin connect");

    assert(!_isConnected);

    _addrInfo = addrInfo;
    _addrInfoPtr = _addrInfo.impl()->begin();
    _connectResult = tryConnect();
    checkPendingError();
    return _isConnected;
}

void TcpSocketImpl::endConnect()
{
    log_trace("ending connect");

    if(_pfd && ! _socket.wbuf())
    {
        _pfd->events &= ~POLLOUT;
    }

    checkPendingError();

    if( _isConnected )
        return;

    try
    {
        while (true)
        {
            pollfd pfd;
            pfd.fd = this->fd();
            pfd.revents = 0;
            pfd.events = POLLOUT;

            log_debug("wait " << timeout() << " ms");
            bool avail = this->wait(this->timeout(), pfd);

            if (avail)
            {
                // something has happened
                int sockerr = checkConnect();
                if (_isConnected)
                    return;

                if (++_addrInfoPtr == _addrInfo.impl()->end())
                {
                    // no more addrInfo - propagate error
                    throw IOError(getErrnoString(sockerr, "connect").c_str());
                }
            }
            else if (++_addrInfoPtr == _addrInfo.impl()->end())
            {
                log_debug("timeout");
                throw IOTimeout();
            }

            close();

            _connectResult = tryConnect();
            if (_isConnected)
                return;
            checkPendingError();
        }
    }
    catch(...)
    {
        close();
        throw;
    }
}

void TcpSocketImpl::accept(const TcpServer& server, unsigned flags)
{
    socklen_t peeraddr_len = sizeof(_peeraddr);

    _fd = server.impl().accept(flags, reinterpret_cast <struct sockaddr*>(&_peeraddr), peeraddr_len);

    if( _fd < 0 )
        throw SystemError("accept");

#ifdef HAVE_ACCEPT4
    IODeviceImpl::open(_fd, false, false);
#else
    IODeviceImpl::open(_fd, true, inherit);
#endif
    //TODO ECONNABORTED EINTR EPERM

    _isConnected = true;
    log_debug( "accepted from " << getPeerAddr());
}

void TcpSocketImpl::initWait(pollfd& pfd)
{
    IODeviceImpl::initWait(pfd);

    if( ! _isConnected )
    {
        log_debug("not connected, setting POLLOUT ");
        pfd.events = POLLOUT;
    }
}

bool TcpSocketImpl::checkPollEvent(pollfd& pfd)
{
    log_debug("checkPollEvent " << pfd.revents);

    if( _isConnected )
        return IODeviceImpl::checkPollEvent(pfd);

    if ( pfd.revents & POLLERR )
    {
        AddrInfoImpl::const_iterator ptr = _addrInfoPtr;
        if (++ptr == _addrInfo.impl()->end())
        {
            // not really connected but error
            // end of addrinfo list means that no working addrinfo was found
            log_debug("no more addrinfos found");
            _socket.connected.send(_socket);
            return true;
        }
        else
        {
            _addrInfoPtr = ptr;

            close();
            _connectResult = tryConnect();

            if (_isConnected || _connectResult.second)
            {
                // immediate success or error
                log_debug("connected successfully");
                _socket.connected.send(_socket);
            }
            else
                // by closing the previous file handle _pfd is set to 0.
                // creating a new socket in tryConnect may also change the value of fd.
                initializePoll(&pfd, 1);

            return _isConnected;
        }
    }
    else if( pfd.revents & POLLOUT )
    {
        int sockerr = checkConnect();
        if (_isConnected)
        {
            _socket.connected.send(_socket);
            return true;
        }

        // something went wrong - look for next addrInfo
        log_debug("sockerr is " << sockerr << " try next");
        if (++_addrInfoPtr == _addrInfo.impl()->end())
        {
            // no more addrInfo - propagate error
            _connectResult = std::pair<int, const char*>(sockerr, "connect");
            _socket.connected.send(_socket);
            return true;
        }

        _connectResult = tryConnect();
        if (_isConnected)
        {
            _socket.connected.send(_socket);
            return true;
        }
    }

    return false;
}

} // namespace net

} // namespace cxxtools
<commit_msg>fix compile error in tcpsocketimpl<commit_after>/*
 * Copyright (C) 2009 Marc Boris Duerner, Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#ifdef HAVE_ACCEPT4
#include <sys/types.h>
#include <sys/socket.h>
#endif

#include "tcpsocketimpl.h"
#include "tcpserverimpl.h"
#include "cxxtools/net/tcpserver.h"
#include "cxxtools/net/tcpsocket.h"
#include "cxxtools/systemerror.h"
#include "cxxtools/ioerror.h"
#include "cxxtools/log.h"
#include "config.h"
#include "error.h"
#include <cerrno>
#include <cstring>
#include <cassert>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

log_define("cxxtools.net.tcpsocket.impl")

namespace cxxtools
{

namespace net
{

void formatIp(const sockaddr_storage& addr, std::string& str)
{
#ifdef HAVE_INET_NTOP
    const sockaddr_in* sa = reinterpret_cast<const sockaddr_in*>(&addr);
    char strbuf[INET6_ADDRSTRLEN + 1];
    const char* p = inet_ntop(sa->sin_family, &sa->sin_addr, strbuf, sizeof(strbuf));
    str = (p == 0 ? "-" : strbuf);
#else
    static cxxtools::Mutex monitor;
    cxxtools::MutexLock lock(monitor);

    const sockaddr_in* sa = reinterpret_cast<const sockaddr_in*>(&addr);
    const char* p = inet_ntoa(sa->sin_addr);
    if (p)
        str = p;
    else
        str.clear();
#endif
}

TcpSocketImpl::TcpSocketImpl(TcpSocket& socket)
: IODeviceImpl(socket)
, _socket(socket)
, _isConnected(false)
{
}

TcpSocketImpl::~TcpSocketImpl()
{
    assert(_pfd == 0);
}

void TcpSocketImpl::close()
{
    log_debug("close socket " << _fd);
    IODeviceImpl::close();
    _isConnected = false;
}

std::string TcpSocketImpl::getSockAddr() const
{
    struct sockaddr_storage addr;

    socklen_t slen = sizeof(addr);
    if (::getsockname(fd(), reinterpret_cast<struct sockaddr*>(&addr), &slen) < 0)
        throw SystemError("getsockname");

    std::string ret;
    formatIp(addr, ret);
    return ret;
}

std::string TcpSocketImpl::getPeerAddr() const
{
    std::string ret;
    formatIp(_peeraddr, ret);
    return ret;
}

void TcpSocketImpl::connect(const AddrInfo& addrInfo)
{
    log_debug("connect");
    this->beginConnect(addrInfo);
    this->endConnect();
}

int TcpSocketImpl::checkConnect()
{
    log_trace("checkConnect");

    int sockerr;
    socklen_t optlen = sizeof(sockerr);

    // check for socket error
    if( ::getsockopt(this->fd(), SOL_SOCKET, SO_ERROR, &sockerr, &optlen) != 0 )
    {
        // getsockopt failed
        int e = errno;
        close();
        throw SystemError(e, "getsockopt");
    }

    if (sockerr == 0)
    {
        log_debug("connected successfully to " << getPeerAddr());
        _isConnected = true;
    }

    return sockerr;
}

void TcpSocketImpl::checkPendingError()
{
    if (_connectResult.second)
    {
        std::pair<int, const char*> p = _connectResult;
        _connectResult = std::pair<int, const char*>(0, 0);

        if (p.first)
        {
            throw IOError(getErrnoString(p.first, p.second).c_str());
        }
        else
        {
            throw IOError("invalid address information");
        }
    }
}

std::pair<int, const char*> TcpSocketImpl::tryConnect()
{
    log_trace("tryConnect");

    assert(_fd == -1);

    if (_addrInfoPtr == _addrInfo.impl()->end())
    {
        log_debug("no more address informations");
        return std::pair<int, const char*>(0, "invalid address information");
    }

    while (true)
    {
        int fd;
        while (true)
        {
            log_debug("create socket");
            fd = ::socket(_addrInfoPtr->ai_family, SOCK_STREAM, 0);
            if (fd >= 0)
                break;

            if (++_addrInfoPtr == _addrInfo.impl()->end())
                return std::pair<int, const char*>(errno, "socket");
        }

        IODeviceImpl::open(fd, true, false);

        std::memmove(&_peeraddr, _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen);

        log_debug("created socket " << _fd << " max: " << FD_SETSIZE);

        if( ::connect(this->fd(), _addrInfoPtr->ai_addr, _addrInfoPtr->ai_addrlen) == 0 )
        {
            _isConnected = true;
            log_debug("connected successfully to " << getPeerAddr());
            break;
        }

        if (errno == EINPROGRESS)
        {
            log_debug("connect in progress");
            break;
        }

        close();
        if (++_addrInfoPtr == _addrInfo.impl()->end())
            return std::pair<int, const char*>(errno, "connect");
    }

    return std::pair<int, const char*>(0, 0);
}

bool TcpSocketImpl::beginConnect(const AddrInfo& addrInfo)
{
    log_trace("begin connect");

    assert(!_isConnected);

    _addrInfo = addrInfo;
    _addrInfoPtr = _addrInfo.impl()->begin();
    _connectResult = tryConnect();
    checkPendingError();
    return _isConnected;
}

void TcpSocketImpl::endConnect()
{
    log_trace("ending connect");

    if(_pfd && ! _socket.wbuf())
    {
        _pfd->events &= ~POLLOUT;
    }

    checkPendingError();

    if( _isConnected )
        return;

    try
    {
        while (true)
        {
            pollfd pfd;
            pfd.fd = this->fd();
            pfd.revents = 0;
            pfd.events = POLLOUT;

            log_debug("wait " << timeout() << " ms");
            bool avail = this->wait(this->timeout(), pfd);

            if (avail)
            {
                // something has happened
                int sockerr = checkConnect();
                if (_isConnected)
                    return;

                if (++_addrInfoPtr == _addrInfo.impl()->end())
                {
                    // no more addrInfo - propagate error
                    throw IOError(getErrnoString(sockerr, "connect").c_str());
                }
            }
            else if (++_addrInfoPtr == _addrInfo.impl()->end())
            {
                log_debug("timeout");
                throw IOTimeout();
            }

            close();

            _connectResult = tryConnect();
            if (_isConnected)
                return;
            checkPendingError();
        }
    }
    catch(...)
    {
        close();
        throw;
    }
}

void TcpSocketImpl::accept(const TcpServer& server, unsigned flags)
{
    socklen_t peeraddr_len = sizeof(_peeraddr);

    _fd = server.impl().accept(flags, reinterpret_cast <struct sockaddr*>(&_peeraddr), peeraddr_len);

    if( _fd < 0 )
        throw SystemError("accept");

#ifdef HAVE_ACCEPT4
    IODeviceImpl::open(_fd, false, false);
#else
    bool inherit = (flags & TcpSocket::INHERIT) != 0;
    IODeviceImpl::open(_fd, true, inherit);
#endif
    //TODO ECONNABORTED EINTR EPERM

    _isConnected = true;
    log_debug( "accepted from " << getPeerAddr());
}

void TcpSocketImpl::initWait(pollfd& pfd)
{
    IODeviceImpl::initWait(pfd);

    if( ! _isConnected )
    {
        log_debug("not connected, setting POLLOUT ");
        pfd.events = POLLOUT;
    }
}

bool TcpSocketImpl::checkPollEvent(pollfd& pfd)
{
    log_debug("checkPollEvent " << pfd.revents);

    if( _isConnected )
        return IODeviceImpl::checkPollEvent(pfd);

    if ( pfd.revents & POLLERR )
    {
        AddrInfoImpl::const_iterator ptr = _addrInfoPtr;
        if (++ptr == _addrInfo.impl()->end())
        {
            // not really connected but error
            // end of addrinfo list means that no working addrinfo was found
            log_debug("no more addrinfos found");
            _socket.connected.send(_socket);
            return true;
        }
        else
        {
            _addrInfoPtr = ptr;

            close();
            _connectResult = tryConnect();

            if (_isConnected || _connectResult.second)
            {
                // immediate success or error
                log_debug("connected successfully");
                _socket.connected.send(_socket);
            }
            else
                // by closing the previous file handle _pfd is set to 0.
                // creating a new socket in tryConnect may also change the value of fd.
                initializePoll(&pfd, 1);

            return _isConnected;
        }
    }
    else if( pfd.revents & POLLOUT )
    {
        int sockerr = checkConnect();
        if (_isConnected)
        {
            _socket.connected.send(_socket);
            return true;
        }

        // something went wrong - look for next addrInfo
        log_debug("sockerr is " << sockerr << " try next");
        if (++_addrInfoPtr == _addrInfo.impl()->end())
        {
            // no more addrInfo - propagate error
            _connectResult = std::pair<int, const char*>(sockerr, "connect");
            _socket.connected.send(_socket);
            return true;
        }

        _connectResult = tryConnect();
        if (_isConnected)
        {
            _socket.connected.send(_socket);
            return true;
        }
    }

    return false;
}

} // namespace net

} // namespace cxxtools
<|endoftext|>


<commit_before>#include "FPSRole.h"
#include "Engine.h"
#include "Creature.h"
#include "AnimationBlend.h"
#include "WorldEffect.h"

CFPSRole::CFPSRole(void)
{
	m_nFire = 0;
	m_fAniCoolingTime = 0;
	m_fAniNowCoolingTime = 0;
	m_fSudCoolingTime = 0;
	m_fEmitCoolingTime = 0;

	m_fEmitNowCoolingTime = 0;
	m_fSudNowCoolingTime = 0;

	m_strMuzzleBone = "";
	m_pArmsMesh = NULL;
	m_pBulletParticle = NULL;
	m_strBulletName = "";
	m_strMuzzleEffect  = "";
}
CFPSRole::~CFPSRole(void)
{
	g_Engine.pGame->RemoveNode(m_pBulletParticle);
	g_Engine.pGame->RemoveNode(m_pMuzzleEffect);
}

int CFPSRole::Init( int nRoleID,const char* strCharFile )
{
	if(CRoleBase::Init(nRoleID,strCharFile))
	{
		m_pStand[0] = (CAnimationBlendRotate*)m_pCreature->GetAnimationBlend("stand_h");
		m_pFire[0] = (CAnimationBlendRotate*)m_pCreature->GetAnimationBlend("fire_h");
		m_pStand[1] = (CAnimationBlendRotate*)m_pCreature->GetAnimationBlend("stand_v");
		m_pFire[1] = (CAnimationBlendRotate*)m_pCreature->GetAnimationBlend("fire_v");
		m_pRun[0] = (CAnimationBlendDual*)m_pCreature->GetAnimationBlend("run_h");
		m_pRun[1] = (CAnimationBlendDual*)m_pCreature->GetAnimationBlend("run_v");

		m_fAniNowCoolingTime = 0.0f;
		m_fAniCoolingTime = 1.0f / m_pFire[0]->GetTriggerSpeed();
		m_fEmitNowCoolingTime = 0;
		m_fSudNowCoolingTime = 0;

		m_fSudCoolingTime = m_fAniCoolingTime  * 4.0f; //ֵ
		m_fEmitCoolingTime = m_fAniCoolingTime * 3.0f;//ֵ

		m_pBulletParticle = (CObjectParticles*)g_Engine.pGame->LoadNode(m_strBulletName);
		m_pBulletParticle->GetTracker(TRACKER_CUSTOM)->SetTrackValue(0,0.0f,vec4(1.0f,1.0f,1.0f,0.8f));
		m_pBulletParticle->SetName(CUtilStr::Format("%d",m_nRoleID));

		m_pMuzzleEffect = (CWorldEffect*)g_Engine.pGame->LoadNode(m_strMuzzleEffect);
		m_pMuzzleEffect->Stop();

		m_pMuzzleEffect->SetLoop(0);
		m_pMuzzleEffect->SetLoopCount(1);

	}
	return 1;//always return 1;
}

void CFPSRole::OnKeyFrame( _ActionCallback_KeyFrame* pKeyInfo )
{
	//I will finish this function later.
}

void CFPSRole::OnActionComplete( _ActionCallback_Complete* pActInfo )
{
	return CRoleBase::OnActionComplete(pActInfo);
}

void CFPSRole::SetPaceAnimationF_B( int nF_B )
{
	switch(nF_B)
	{
	case 0:
		m_pRun[0]->CloseBlend();
		break;
	case 1:
		m_pRun[0]->PlayAnimationA();
		break;
	case 2:
		m_pRun[0]->PlayAnimationB();
		break;
	}
}

void CFPSRole::OnFire( float fCoolingTime )
{

}<commit_msg>Signed-off-by: mrlitong <litongtongxue@gmail.com><commit_after>#include "FPSRole.h"
#include "Engine.h"
#include "Creature.h"
#include "AnimationBlend.h"
#include "WorldEffect.h"

CFPSRole::CFPSRole(void)
{
	m_nFire = 0;
	m_fAniCoolingTime = 0;
	m_fAniNowCoolingTime = 0;
	m_fSudCoolingTime = 0;
	m_fEmitCoolingTime = 0;

	m_fEmitNowCoolingTime = 0;
	m_fSudNowCoolingTime = 0;

	m_strMuzzleBone = "";
	m_pArmsMesh = NULL;
	m_pBulletParticle = NULL;
	m_strBulletName = "";
	m_strMuzzleEffect  = "";
}
CFPSRole::~CFPSRole(void)
{
	g_Engine.pGame->RemoveNode(m_pBulletParticle);
	g_Engine.pGame->RemoveNode(m_pMuzzleEffect);
}

int CFPSRole::Init( int nRoleID,const char* strCharFile )
{
	if(CRoleBase::Init(nRoleID,strCharFile))
	{
		m_pStand[0] = (CAnimationBlendRotate*)m_pCreature->GetAnimationBlend("stand_h");
		m_pFire[0] = (CAnimationBlendRotate*)m_pCreature->GetAnimationBlend("fire_h");
		m_pStand[1] = (CAnimationBlendRotate*)m_pCreature->GetAnimationBlend("stand_v");
		m_pFire[1] = (CAnimationBlendRotate*)m_pCreature->GetAnimationBlend("fire_v");
		m_pRun[0] = (CAnimationBlendDual*)m_pCreature->GetAnimationBlend("run_h");
		m_pRun[1] = (CAnimationBlendDual*)m_pCreature->GetAnimationBlend("run_v");

		m_fAniNowCoolingTime = 0.0f;
		m_fAniCoolingTime = 1.0f / m_pFire[0]->GetTriggerSpeed();
		m_fEmitNowCoolingTime = 0;
		m_fSudNowCoolingTime = 0;

		m_fSudCoolingTime = m_fAniCoolingTime  * 4.0f; //ֵ
		m_fEmitCoolingTime = m_fAniCoolingTime * 3.0f;//ֵ

		m_pBulletParticle = (CObjectParticles*)g_Engine.pGame->LoadNode(m_strBulletName);
		m_pBulletParticle->GetTracker(TRACKER_CUSTOM)->SetTrackValue(0,0.0f,vec4(1.0f,1.0f,1.0f,0.8f));
		m_pBulletParticle->SetName(CUtilStr::Format("%d",m_nRoleID));

		m_pMuzzleEffect = (CWorldEffect*)g_Engine.pGame->LoadNode(m_strMuzzleEffect);
		m_pMuzzleEffect->Stop();

		m_pMuzzleEffect->SetLoop(0);
		m_pMuzzleEffect->SetLoopCount(1);

	}
	return 1;//always return 1;
}

void CFPSRole::OnKeyFrame( _ActionCallback_KeyFrame* pKeyInfo )
{
	//I will finish this function later.
}

void CFPSRole::OnActionComplete( _ActionCallback_Complete* pActInfo )
{
	return CRoleBase::OnActionComplete(pActInfo);
}

void CFPSRole::SetPaceAnimationF_B( int nF_B )
{
	switch(nF_B)
	{
	case 0:
		m_pRun[0]->CloseBlend();
		break;
	case 1:
		m_pRun[0]->PlayAnimationA();
		break;
	case 2:
		m_pRun[0]->PlayAnimationB();
		break;
	}
}

void CFPSRole::OnFire( float fCoolingTime )
{

}

void CFPSRole::UpdateMuzzleTransform()
{
	m_pFire[0]->LockFrame(2.3f);
	m_pFire[1]->LockFrame(2.3f);
	m_pStand[0]->LockFrame(2.3f);
	m_pStand[1]->LockFrame(2.3f);

}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2019, The DART development contributors
 * All rights reserved.
 *
 * The list of contributors can be found at:
 *   https://github.com/dartsim/dart/blob/master/LICENSE
 *
 * This file is provided under the following "BSD-style" License:
 *   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.
 *   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 HOLDER 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.
 */

#ifndef DART_COMMON_REQUIRESASPECT_HPP_
#define DART_COMMON_REQUIRESASPECT_HPP_

#include "dart/common/SpecializedForAspect.hpp"

namespace dart {
namespace common {

//==============================================================================
/// RequiresAspect allows classes that inherit Composite to know which Aspects
/// are required for their operation. This guarantees that there is no way for
/// a required Aspect do not get unexpectedly removed from their composite.
///
/// Required Aspects are also automatically specialized for.
template <class... OtherRequiredAspects>
class RequiresAspect
{
};

//==============================================================================
template <class ReqAspect>
class RequiresAspect<ReqAspect> : public virtual SpecializedForAspect<ReqAspect>
{
public:
  /// Default constructor. This is where the base Composite is informed that
  /// the Aspect type is required.
  RequiresAspect();
};

//==============================================================================
template <class ReqAspect1, class... OtherReqAspects>
class RequiresAspect<ReqAspect1, OtherReqAspects...>
  : public CompositeJoiner<
        Virtual<RequiresAspect<ReqAspect1> >,
        Virtual<RequiresAspect<OtherReqAspects...> > >
{
};

} // namespace common
} // namespace dart

#include "dart/common/detail/RequiresAspect.hpp"

#endif // DART_COMMON_REQUIRESASPECT_HPP_
<commit_msg>Add missing virtual base class dectoration for RequiresAspect (#1542)<commit_after>/*
 * Copyright (c) 2011-2019, The DART development contributors
 * All rights reserved.
 *
 * The list of contributors can be found at:
 *   https://github.com/dartsim/dart/blob/master/LICENSE
 *
 * This file is provided under the following "BSD-style" License:
 *   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.
 *   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 HOLDER 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.
 */

#ifndef DART_COMMON_REQUIRESASPECT_HPP_
#define DART_COMMON_REQUIRESASPECT_HPP_

#include "dart/common/ClassWithVirtualBase.hpp"
#include "dart/common/SpecializedForAspect.hpp"

namespace dart {
namespace common {

//==============================================================================
/// RequiresAspect allows classes that inherit Composite to know which Aspects
/// are required for their operation. This guarantees that there is no way for
/// a required Aspect do not get unexpectedly removed from their composite.
///
/// Required Aspects are also automatically specialized for.
template <class... OtherRequiredAspects>
class RequiresAspect
{
};

//==============================================================================
DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_BEGIN
template <class ReqAspect>
class RequiresAspect<ReqAspect> : public virtual SpecializedForAspect<ReqAspect>
{
public:
  /// Default constructor. This is where the base Composite is informed that
  /// the Aspect type is required.
  RequiresAspect();
};
DART_DECLARE_CLASS_WITH_VIRTUAL_BASE_END

//==============================================================================
template <class ReqAspect1, class... OtherReqAspects>
class RequiresAspect<ReqAspect1, OtherReqAspects...>
  : public CompositeJoiner<
        Virtual<RequiresAspect<ReqAspect1> >,
        Virtual<RequiresAspect<OtherReqAspects...> > >
{
};

} // namespace common
} // namespace dart

#include "dart/common/detail/RequiresAspect.hpp"

#endif // DART_COMMON_REQUIRESASPECT_HPP_
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ConfigurationControllerBroadcaster.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-03 15:46:07 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SD_FRAMEWORK_CONFIGURATION_CONTROLLER_BROADCASTER_HXX
#define SD_FRAMEWORK_CONFIGURATION_CONTROLLER_BROADCASTER_HXX

#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_XCONFIGURATIONCHANGELISTENER_HPP_
#include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_XCONFIGURATIONCONTROLLER_HPP_
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_FRAMEWORK_CONFIGURATIONCHANGEEVENT_HPP_
#include <com/sun/star/drawing/framework/ConfigurationChangeEvent.hpp>
#endif

#include <comphelper/stl_types.hxx>
#include <vector>
#include <hash_map>

namespace sd { namespace framework {

/** This class manages the set of XConfigurationChangeListeners and
    calls them when the ConfigurationController wants to broadcast an
    event.

    For every registered combination of listener and event type a user data
    object is stored.  This user data object is then given to the listener
    whenever it is called for an event.  With this the listener can use
    a switch statement to handle different event types.
*/
class ConfigurationControllerBroadcaster
{
public:
    /** The given controller is used as origin of thrown exceptions.
    */
    ConfigurationControllerBroadcaster (
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::drawing::framework::XConfigurationController>& rxController);

    /** Add a listener for one type of event.  When one listener is
        interested in more than one event type this method has to be called
        once for every event type.  Alternatively it can register as
        universal listener that will be called for all event types.
        @param rxListener
            A valid reference to a listener.
        @param rsEventType
            The type of event that the listener will be called for.  The
            empty string is a special value in that the listener will be
            called for all event types.
        @param rUserData
            This object is passed to the listener whenever it is called for
            the specified event type.  For different event types different
            user data objects can be provided.
        @throws IllegalArgumentException
            when an empty listener reference is given.
    */
    void AddListener(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::drawing::framework::XConfigurationChangeListener>& rxListener,
        const ::rtl::OUString& rsEventType,
        const ::com::sun::star::uno::Any& rUserData);

    /** Remove all references to the given listener.  When one listener has
        been registered for more than one type of event then it is removed
        for all of them.
        @param rxListener
            A valid reference to a listener.
        @throws IllegalArgumentException
            when an empty listener reference is given.
    */
    void RemoveListener(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::drawing::framework::XConfigurationChangeListener>& rxListener);

    /** Broadcast the given event to all listeners that have been registered
        for its type of event as well as all universal listeners.

        When calling a listener results in a DisposedException being thrown
        the listener is unregistered automatically.
    */
    void NotifyListeners (
        const ::com::sun::star::drawing::framework::ConfigurationChangeEvent& rEvent);

    /** Call all listeners and inform them that the
        ConfigurationController is being disposed.  When this method returns
        the list of registered listeners is empty.  Further calls to
        RemoveListener() are not necessary but do not result in an error.
    */
    void DisposeAndClear (void);

private:
    ::com::sun::star::uno::Reference<
        com::sun::star::drawing::framework::XConfigurationController> mxConfigurationController;
    class ListenerDescriptor {public:
        ::com::sun::star::uno::Reference<
            ::com::sun::star::drawing::framework::XConfigurationChangeListener> mxListener;
        ::com::sun::star::uno::Any maUserData;
    };
    typedef ::std::vector<ListenerDescriptor> ListenerList;
    typedef ::std::hash_map
        <rtl::OUString,
         ListenerList,
         ::comphelper::UStringHash,
         ::comphelper::UStringEqual> ListenerMap;
    ListenerMap maListenerMap;

    /** Broadcast the given event to all listeners in the given list.

        When calling a listener results in a DisposedException being thrown
        the listener is unregistered automatically.
    */
    void NotifyListeners (
        const ListenerList& rList,
        const ::com::sun::star::drawing::framework::ConfigurationChangeEvent& rEvent);
};

} } // end of namespace sd::framework

#endif
<commit_msg>INTEGRATION: CWS presenterview (1.2.22); FILE MERGED 2007/06/18 14:58:38 af 1.2.22.1: #i18486# Added a variant of NotifyListeners.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ConfigurationControllerBroadcaster.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2008-04-03 13:29:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SD_FRAMEWORK_CONFIGURATION_CONTROLLER_BROADCASTER_HXX
#define SD_FRAMEWORK_CONFIGURATION_CONTROLLER_BROADCASTER_HXX

#include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp>
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#include <com/sun/star/drawing/framework/ConfigurationChangeEvent.hpp>

#include <comphelper/stl_types.hxx>
#include <vector>
#include <hash_map>

namespace css = ::com::sun::star;

namespace sd { namespace framework {

/** This class manages the set of XConfigurationChangeListeners and
    calls them when the ConfigurationController wants to broadcast an
    event.

    For every registered combination of listener and event type a user data
    object is stored.  This user data object is then given to the listener
    whenever it is called for an event.  With this the listener can use
    a switch statement to handle different event types.
*/
class ConfigurationControllerBroadcaster
{
public:
    /** The given controller is used as origin of thrown exceptions.
    */
    ConfigurationControllerBroadcaster (
        const css::uno::Reference<
            css::drawing::framework::XConfigurationController>& rxController);

    /** Add a listener for one type of event.  When one listener is
        interested in more than one event type this method has to be called
        once for every event type.  Alternatively it can register as
        universal listener that will be called for all event types.
        @param rxListener
            A valid reference to a listener.
        @param rsEventType
            The type of event that the listener will be called for.  The
            empty string is a special value in that the listener will be
            called for all event types.
        @param rUserData
            This object is passed to the listener whenever it is called for
            the specified event type.  For different event types different
            user data objects can be provided.
        @throws IllegalArgumentException
            when an empty listener reference is given.
    */
    void AddListener(
        const css::uno::Reference<
            css::drawing::framework::XConfigurationChangeListener>& rxListener,
        const ::rtl::OUString& rsEventType,
        const css::uno::Any& rUserData);

    /** Remove all references to the given listener.  When one listener has
        been registered for more than one type of event then it is removed
        for all of them.
        @param rxListener
            A valid reference to a listener.
        @throws IllegalArgumentException
            when an empty listener reference is given.
    */
    void RemoveListener(
        const css::uno::Reference<
            css::drawing::framework::XConfigurationChangeListener>& rxListener);

    /** Broadcast the given event to all listeners that have been registered
        for its type of event as well as all universal listeners.

        When calling a listener results in a DisposedException being thrown
        the listener is unregistered automatically.
    */
    void NotifyListeners (
        const css::drawing::framework::ConfigurationChangeEvent& rEvent);

    /** This convenience variant of NotifyListeners create the event from
        the given arguments.
    */
    void NotifyListeners (
        const ::rtl::OUString& rsEventType,
        const ::css::uno::Reference<css::drawing::framework::XResourceId>& rxResourceId,
        const ::css::uno::Reference<css::drawing::framework::XResource>& rxResourceObject);

    /** Call all listeners and inform them that the
        ConfigurationController is being disposed.  When this method returns
        the list of registered listeners is empty.  Further calls to
        RemoveListener() are not necessary but do not result in an error.
    */
    void DisposeAndClear (void);

private:
    css::uno::Reference<
        com::sun::star::drawing::framework::XConfigurationController> mxConfigurationController;
    class ListenerDescriptor {public:
        css::uno::Reference<
            css::drawing::framework::XConfigurationChangeListener> mxListener;
        css::uno::Any maUserData;
    };
    typedef ::std::vector<ListenerDescriptor> ListenerList;
    typedef ::std::hash_map
        <rtl::OUString,
         ListenerList,
         ::comphelper::UStringHash,
         ::comphelper::UStringEqual> ListenerMap;
    ListenerMap maListenerMap;

    /** Broadcast the given event to all listeners in the given list.

        When calling a listener results in a DisposedException being thrown
        the listener is unregistered automatically.
    */
    void NotifyListeners (
        const ListenerList& rList,
        const css::drawing::framework::ConfigurationChangeEvent& rEvent);
};

} } // end of namespace sd::framework

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/globals.h"
#if defined(HOST_OS_FUCHSIA)

#include "vm/virtual_memory.h"

#include <sys/mman.h>
#include <unistd.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include "platform/assert.h"
#include "vm/allocation.h"
#include "vm/growable_array.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/memory_region.h"
#include "vm/os.h"
#include "vm/os_thread.h"

// #define VIRTUAL_MEMORY_LOGGING 1
#if defined(VIRTUAL_MEMORY_LOGGING)
#define LOG_ERR(msg, ...)                                                      \
  OS::PrintErr("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_INFO(msg, ...)                                                     \
  OS::PrintErr("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define LOG_ERR(msg, ...)
#define LOG_INFO(msg, ...)
#endif  // defined(VIRTUAL_MEMORY_LOGGING)

namespace dart {

DECLARE_FLAG(bool, dual_map_code);
DECLARE_FLAG(bool, write_protect_code);

uword VirtualMemory::page_size_ = 0;
uword VirtualMemory::base_ = 0;

void VirtualMemory::Init() {
  page_size_ = getpagesize();

  // Cache the base of zx_vmar_root_self() which is used to align mappings.
  zx_info_vmar_t buf[1];
  size_t actual;
  size_t avail;
  zx_status_t status =
      zx_object_get_info(zx_vmar_root_self(), ZX_INFO_VMAR, buf,
                         sizeof(zx_info_vmar_t), &actual, &avail);
  if (status != ZX_OK) {
    FATAL1("zx_object_get_info failed: %s\n", zx_status_get_string(status));
  }
  base_ = buf[0].base;
}

static void Unmap(zx_handle_t vmar, uword start, uword end) {
  ASSERT(start <= end);
  const uword size = end - start;
  if (size == 0) {
    return;
  }

  zx_status_t status = zx_vmar_unmap(vmar, start, size);
  if (status != ZX_OK) {
    FATAL1("zx_vmar_unmap failed: %s\n", zx_status_get_string(status));
  }
}

static void* MapAligned(zx_handle_t vmar,
                        zx_handle_t vmo,
                        zx_vm_option_t options,
                        uword size,
                        uword alignment,
                        uword vmar_base,
                        uword padded_size) {
  // Allocate a larger mapping than needed in order to find a suitable aligned
  // mapping within it.
  uword base;
  zx_status_t status =
      zx_vmar_map(vmar, options, 0, vmo, 0u, padded_size, &base);
  LOG_INFO("zx_vmar_map(%u, 0x%lx, 0x%lx)\n", options, base, padded_size);
  if (status != ZX_OK) {
    LOG_ERR("zx_vmar_map(%u, 0x%lx, 0x%lx) failed: %s\n", options, base,
            padded_size, zx_status_get_string(status));
    return NULL;
  }

  // Allocate a smaller aligned mapping inside the larger mapping.
  const uword orig_base = base;
  const uword aligned_base = Utils::RoundUp(base, alignment);
  const zx_vm_option_t overwrite_options = options | ZX_VM_SPECIFIC_OVERWRITE;
  status = zx_vmar_map(vmar, overwrite_options, aligned_base - vmar_base, vmo,
                       0u, size, &base);
  LOG_INFO("zx_vmar_map(%u, 0x%lx, 0x%lx)\n", overwrite_options,
           aligned_base - vmar_base, size);

  if (status != ZX_OK) {
    LOG_ERR("zx_vmar_map(%u, 0x%lx, 0x%lx) failed: %s\n", overwrite_options,
            aligned_base - vmar_base, size, zx_status_get_string(status));
    return NULL;
  }
  ASSERT(base == aligned_base);

  // Unmap the unused prefix and suffix. See ZX-3917 and/or ZX-1173.
  if (orig_base != base) {
    status = zx_vmar_unmap(vmar, orig_base, base - orig_base);
    if (status != ZX_OK) {
      LOG_ERR("zx_vmar_unmap(0x%lx, 0x%lx) failed: %s\n", orig_base,
              base - orig_base, zx_status_get_string(status));
    }
  }
  if ((orig_base + padded_size) != (base + size)) {
    status = zx_vmar_unmap(vmar, base + size,
                           (orig_base + padded_size) - (base + size));
    if (status != ZX_OK) {
      LOG_ERR("zx_vmar_unmap(0x%lx, 0x%lx) failed: %s\n", base + size,
              (orig_base + padded_size) - (base + size),
              zx_status_get_string(status));
    }
  }

  return reinterpret_cast<void*>(base);
}

VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
                                              intptr_t alignment,
                                              bool is_executable,
                                              const char* name) {
  // When FLAG_write_protect_code is active, code memory (indicated by
  // is_executable = true) is allocated as non-executable and later
  // changed to executable via VirtualMemory::Protect, which requires
  // ZX_RIGHT_EXECUTE on the underlying VMO.
  // In addition, dual mapping of the same underlying code memory is provided.
  const bool dual_mapping =
      is_executable && FLAG_write_protect_code && FLAG_dual_map_code;

  ASSERT(Utils::IsAligned(size, page_size_));
  ASSERT(Utils::IsPowerOfTwo(alignment));
  ASSERT(Utils::IsAligned(alignment, page_size_));
  const intptr_t padded_size = size + alignment - page_size_;

  zx_handle_t vmar = zx_vmar_root_self();
  zx_handle_t vmo = ZX_HANDLE_INVALID;
  zx_status_t status = zx_vmo_create(size, 0u, &vmo);
  if (status != ZX_OK) {
    LOG_ERR("zx_vmo_create(0x%lx) failed: %s\n", size,
            zx_status_get_string(status));
    return NULL;
  }

  if (name != NULL) {
    zx_object_set_property(vmo, ZX_PROP_NAME, name, strlen(name));
  }

  if (is_executable) {
    // Add ZX_RIGHT_EXECUTE permission to VMO, so it can be mapped
    // into memory as executable (now or later).
    status = zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo);
    if (status != ZX_OK) {
      LOG_ERR("zx_vmo_replace_as_executable() failed: %s\n",
              zx_status_get_string(status));
      return NULL;
    }
  }

  const zx_vm_option_t region_options =
      ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
      ((is_executable && !FLAG_write_protect_code) ? ZX_VM_PERM_EXECUTE : 0);
  void* region_ptr = MapAligned(vmar, vmo, region_options, size, alignment,
                                base_, padded_size);
  if (region_ptr == NULL) {
    return NULL;
  }
  MemoryRegion region(region_ptr, size);

  VirtualMemory* result;

  if (dual_mapping) {
    // ZX_VM_PERM_EXECUTE is added later via VirtualMemory::Protect.
    const zx_vm_option_t alias_options = ZX_VM_PERM_READ;
    void* alias_ptr = MapAligned(vmar, vmo, alias_options, size, alignment,
                                 base_, padded_size);
    if (alias_ptr == NULL) {
      const uword region_base = reinterpret_cast<uword>(region_ptr);
      Unmap(vmar, region_base, region_base + size);
      return NULL;
    }
    ASSERT(region_ptr != alias_ptr);
    MemoryRegion alias(alias_ptr, size);
    result = new VirtualMemory(region, alias, region);
  } else {
    result = new VirtualMemory(region, region, region);
  }
  zx_handle_close(vmo);
  return result;
}

VirtualMemory::~VirtualMemory() {
  // Reserved region may be empty due to VirtualMemory::Truncate.
  if (vm_owns_region() && reserved_.size() != 0) {
    Unmap(zx_vmar_root_self(), reserved_.start(), reserved_.end());
    LOG_INFO("zx_vmar_unmap(0x%lx, 0x%lx) success\n", reserved_.start(),
             reserved_.size());

    const intptr_t alias_offset = AliasOffset();
    if (alias_offset != 0) {
      Unmap(zx_vmar_root_self(), reserved_.start() + alias_offset,
            reserved_.end() + alias_offset);
      LOG_INFO("zx_vmar_unmap(0x%lx, 0x%lx) success\n",
               reserved_.start() + alias_offset, reserved_.size());
    }
  }
}

void VirtualMemory::FreeSubSegment(void* address, intptr_t size) {
  const uword start = reinterpret_cast<uword>(address);
  Unmap(zx_vmar_root_self(), start, start + size);
  LOG_INFO("zx_vmar_unmap(0x%p, 0x%lx) success\n", address, size);
}

void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
#if defined(DEBUG)
  Thread* thread = Thread::Current();
  ASSERT((thread == nullptr) || thread->IsMutatorThread() ||
         thread->isolate()->mutator_thread()->IsAtSafepoint());
#endif
  const uword start_address = reinterpret_cast<uword>(address);
  const uword end_address = start_address + size;
  const uword page_address = Utils::RoundDown(start_address, PageSize());
  uint32_t prot = 0;
  switch (mode) {
    case kNoAccess:
      prot = 0;
      break;
    case kReadOnly:
      prot = ZX_VM_PERM_READ;
      break;
    case kReadWrite:
      prot = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE;
      break;
    case kReadExecute:
      prot = ZX_VM_PERM_READ | ZX_VM_PERM_EXECUTE;
      break;
    case kReadWriteExecute:
      prot = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE;
      break;
  }
  zx_status_t status = zx_vmar_protect(zx_vmar_root_self(), prot, page_address,
                                       end_address - page_address);
  LOG_INFO("zx_vmar_protect(%u, 0x%lx, 0x%lx)\n", prot, page_address,
           end_address - page_address);
  if (status != ZX_OK) {
    FATAL3("zx_vmar_protect(0x%lx, 0x%lx) failed: %s\n", page_address,
           end_address - page_address, zx_status_get_string(status));
  }
}

}  // namespace dart

#endif  // defined(HOST_OS_FUCHSIA)
<commit_msg>[fuchsia] Use Unmap() instead of zx_vmar_unmap()<commit_after>// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/globals.h"
#if defined(HOST_OS_FUCHSIA)

#include "vm/virtual_memory.h"

#include <sys/mman.h>
#include <unistd.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include "platform/assert.h"
#include "vm/allocation.h"
#include "vm/growable_array.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/memory_region.h"
#include "vm/os.h"
#include "vm/os_thread.h"

// #define VIRTUAL_MEMORY_LOGGING 1
#if defined(VIRTUAL_MEMORY_LOGGING)
#define LOG_ERR(msg, ...)                                                      \
  OS::PrintErr("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG_INFO(msg, ...)                                                     \
  OS::PrintErr("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
#else
#define LOG_ERR(msg, ...)
#define LOG_INFO(msg, ...)
#endif  // defined(VIRTUAL_MEMORY_LOGGING)

namespace dart {

DECLARE_FLAG(bool, dual_map_code);
DECLARE_FLAG(bool, write_protect_code);

uword VirtualMemory::page_size_ = 0;
uword VirtualMemory::base_ = 0;

void VirtualMemory::Init() {
  page_size_ = getpagesize();

  // Cache the base of zx_vmar_root_self() which is used to align mappings.
  zx_info_vmar_t buf[1];
  size_t actual;
  size_t avail;
  zx_status_t status =
      zx_object_get_info(zx_vmar_root_self(), ZX_INFO_VMAR, buf,
                         sizeof(zx_info_vmar_t), &actual, &avail);
  if (status != ZX_OK) {
    FATAL1("zx_object_get_info failed: %s\n", zx_status_get_string(status));
  }
  base_ = buf[0].base;
}

static void Unmap(zx_handle_t vmar, uword start, uword end) {
  ASSERT(start <= end);
  const uword size = end - start;
  if (size == 0) {
    return;
  }

  zx_status_t status = zx_vmar_unmap(vmar, start, size);
  if (status != ZX_OK) {
    FATAL1("zx_vmar_unmap failed: %s\n", zx_status_get_string(status));
  }
}

static void* MapAligned(zx_handle_t vmar,
                        zx_handle_t vmo,
                        zx_vm_option_t options,
                        uword size,
                        uword alignment,
                        uword vmar_base,
                        uword padded_size) {
  // Allocate a larger mapping than needed in order to find a suitable aligned
  // mapping within it.
  uword base;
  zx_status_t status =
      zx_vmar_map(vmar, options, 0, vmo, 0u, padded_size, &base);
  LOG_INFO("zx_vmar_map(%u, 0x%lx, 0x%lx)\n", options, base, padded_size);
  if (status != ZX_OK) {
    LOG_ERR("zx_vmar_map(%u, 0x%lx, 0x%lx) failed: %s\n", options, base,
            padded_size, zx_status_get_string(status));
    return NULL;
  }

  // Allocate a smaller aligned mapping inside the larger mapping.
  const uword orig_base = base;
  const uword aligned_base = Utils::RoundUp(base, alignment);
  const zx_vm_option_t overwrite_options = options | ZX_VM_SPECIFIC_OVERWRITE;
  status = zx_vmar_map(vmar, overwrite_options, aligned_base - vmar_base, vmo,
                       0u, size, &base);
  LOG_INFO("zx_vmar_map(%u, 0x%lx, 0x%lx)\n", overwrite_options,
           aligned_base - vmar_base, size);

  if (status != ZX_OK) {
    LOG_ERR("zx_vmar_map(%u, 0x%lx, 0x%lx) failed: %s\n", overwrite_options,
            aligned_base - vmar_base, size, zx_status_get_string(status));
    return NULL;
  }
  ASSERT(base == aligned_base);

  // Unmap the unused prefix and suffix.
  Unmap(vmar, orig_base, base);
  Unmap(vmar, base + size, orig_base + padded_size);

  return reinterpret_cast<void*>(base);
}

VirtualMemory* VirtualMemory::AllocateAligned(intptr_t size,
                                              intptr_t alignment,
                                              bool is_executable,
                                              const char* name) {
  // When FLAG_write_protect_code is active, code memory (indicated by
  // is_executable = true) is allocated as non-executable and later
  // changed to executable via VirtualMemory::Protect, which requires
  // ZX_RIGHT_EXECUTE on the underlying VMO.
  // In addition, dual mapping of the same underlying code memory is provided.
  const bool dual_mapping =
      is_executable && FLAG_write_protect_code && FLAG_dual_map_code;

  ASSERT(Utils::IsAligned(size, page_size_));
  ASSERT(Utils::IsPowerOfTwo(alignment));
  ASSERT(Utils::IsAligned(alignment, page_size_));
  const intptr_t padded_size = size + alignment - page_size_;

  zx_handle_t vmar = zx_vmar_root_self();
  zx_handle_t vmo = ZX_HANDLE_INVALID;
  zx_status_t status = zx_vmo_create(size, 0u, &vmo);
  if (status != ZX_OK) {
    LOG_ERR("zx_vmo_create(0x%lx) failed: %s\n", size,
            zx_status_get_string(status));
    return NULL;
  }

  if (name != NULL) {
    zx_object_set_property(vmo, ZX_PROP_NAME, name, strlen(name));
  }

  if (is_executable) {
    // Add ZX_RIGHT_EXECUTE permission to VMO, so it can be mapped
    // into memory as executable (now or later).
    status = zx_vmo_replace_as_executable(vmo, ZX_HANDLE_INVALID, &vmo);
    if (status != ZX_OK) {
      LOG_ERR("zx_vmo_replace_as_executable() failed: %s\n",
              zx_status_get_string(status));
      return NULL;
    }
  }

  const zx_vm_option_t region_options =
      ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
      ((is_executable && !FLAG_write_protect_code) ? ZX_VM_PERM_EXECUTE : 0);
  void* region_ptr = MapAligned(vmar, vmo, region_options, size, alignment,
                                base_, padded_size);
  if (region_ptr == NULL) {
    return NULL;
  }
  MemoryRegion region(region_ptr, size);

  VirtualMemory* result;

  if (dual_mapping) {
    // ZX_VM_PERM_EXECUTE is added later via VirtualMemory::Protect.
    const zx_vm_option_t alias_options = ZX_VM_PERM_READ;
    void* alias_ptr = MapAligned(vmar, vmo, alias_options, size, alignment,
                                 base_, padded_size);
    if (alias_ptr == NULL) {
      const uword region_base = reinterpret_cast<uword>(region_ptr);
      Unmap(vmar, region_base, region_base + size);
      return NULL;
    }
    ASSERT(region_ptr != alias_ptr);
    MemoryRegion alias(alias_ptr, size);
    result = new VirtualMemory(region, alias, region);
  } else {
    result = new VirtualMemory(region, region, region);
  }
  zx_handle_close(vmo);
  return result;
}

VirtualMemory::~VirtualMemory() {
  // Reserved region may be empty due to VirtualMemory::Truncate.
  if (vm_owns_region() && reserved_.size() != 0) {
    Unmap(zx_vmar_root_self(), reserved_.start(), reserved_.end());
    LOG_INFO("zx_vmar_unmap(0x%lx, 0x%lx) success\n", reserved_.start(),
             reserved_.size());

    const intptr_t alias_offset = AliasOffset();
    if (alias_offset != 0) {
      Unmap(zx_vmar_root_self(), reserved_.start() + alias_offset,
            reserved_.end() + alias_offset);
      LOG_INFO("zx_vmar_unmap(0x%lx, 0x%lx) success\n",
               reserved_.start() + alias_offset, reserved_.size());
    }
  }
}

void VirtualMemory::FreeSubSegment(void* address, intptr_t size) {
  const uword start = reinterpret_cast<uword>(address);
  Unmap(zx_vmar_root_self(), start, start + size);
  LOG_INFO("zx_vmar_unmap(0x%p, 0x%lx) success\n", address, size);
}

void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
#if defined(DEBUG)
  Thread* thread = Thread::Current();
  ASSERT((thread == nullptr) || thread->IsMutatorThread() ||
         thread->isolate()->mutator_thread()->IsAtSafepoint());
#endif
  const uword start_address = reinterpret_cast<uword>(address);
  const uword end_address = start_address + size;
  const uword page_address = Utils::RoundDown(start_address, PageSize());
  uint32_t prot = 0;
  switch (mode) {
    case kNoAccess:
      prot = 0;
      break;
    case kReadOnly:
      prot = ZX_VM_PERM_READ;
      break;
    case kReadWrite:
      prot = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE;
      break;
    case kReadExecute:
      prot = ZX_VM_PERM_READ | ZX_VM_PERM_EXECUTE;
      break;
    case kReadWriteExecute:
      prot = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_PERM_EXECUTE;
      break;
  }
  zx_status_t status = zx_vmar_protect(zx_vmar_root_self(), prot, page_address,
                                       end_address - page_address);
  LOG_INFO("zx_vmar_protect(%u, 0x%lx, 0x%lx)\n", prot, page_address,
           end_address - page_address);
  if (status != ZX_OK) {
    FATAL3("zx_vmar_protect(0x%lx, 0x%lx) failed: %s\n", page_address,
           end_address - page_address, zx_status_get_string(status));
  }
}

}  // namespace dart

#endif  // defined(HOST_OS_FUCHSIA)
<|endoftext|>


<commit_before>#include <iostream>
#include "subprocess.hpp"
#include <cstring>

// Note: this works even for ffmpeg with image2pipe to get err and out stream!
int manual_subprocess(const char* const* cmd)
{
	struct subprocess_s process;
	if(subprocess_create(cmd, subprocess_option_enable_async | subprocess_option_inherit_environment | subprocess_option_no_window, &process) != 0)
		return -1;

	int nchars = 128, nerrchars = nchars * 2;
	char buf[nchars], errbuf[nerrchars];
	memset(buf, '\0', nchars);
	memset(errbuf, '\0', nerrchars);
	int ret2 = subprocess_read_stderr(&process, errbuf, nerrchars);
	if(ret2 == 0)
	{
		std::cout << "subprocess_read_stderr failure." << std::endl;
		return -1;
	}
	std::cout << "err ret:" << ret2 << std::endl;
	std::cout << "errbuf:" << errbuf << std::endl;
	int ret = subprocess_read_stdout(&process, buf, nchars); // struct subprocess_s *const process, char *const buffer,unsigned size);
	if(ret == 0) // TODO: this handling is missing in struct initialization for SPREAD
	{
		std::cout << "subprocess_read_stdout failure." << std::endl;
		return -1;
	}
	std::cout << "out ret:" << ret << std::endl;
	std::cout << "out buf:" << buf << std::endl;
	subprocess_destroy(&process);
	return 0;
}

int manual_subprocess_class(const char* const* cmd)
{
    Subprocess sp{cmd};

	int nchars = 128, nerrchars = nchars * 2;
	char buf[nchars], errbuf[nerrchars];
	memset(buf, '\0', nchars);
	memset(errbuf, '\0', nerrchars);
	int ret2 = sp.read_from_stderr(errbuf, nerrchars);
	if(ret2 == 0)
	{
		std::cout << "subprocess_read_stderr completion of process, no data read." << std::endl;
		return -1;
	}
	std::cout << "err ret:" << ret2 << std::endl;
	std::cout << "errbuf:" << errbuf << std::endl;
	int ret = sp.read_from_stdout(buf, nchars); // struct subprocess_s *const process, char *const buffer,unsigned size);
	if(ret == 0) // TODO: this handling is missing in struct initialization for SPREAD
	{
		std::cout << "subprocess_read_stdout completion of process, no data read." << std::endl;
		return -1;
	}
	std::cout << "out ret:" << ret << std::endl;
	std::cout << "out buf:" << buf << std::endl;
	return 0;
}

int main(int argc,char** argv)
{
    std::cout << "Hello, world" << std::endl;
    //const char* cmd[]={"/usr/bin/ffmpeg",0}; // works if don't use errstream
	//const char *const cmd[] = {"/usr/bin/ffmpeg", "-v","24","-pix_fmts", 0};
    const char* cmd[] = {"/usr/bin/ffmpeg", "-i", "test.mp4", "-pix_fmt", "rgba", "-vcodec", "rawvideo", "-f", "rawvideo", "-", 0};

	manual_subprocess_class(cmd);

    return 0;
}
<commit_msg>Update test_subprocess_oop.cpp<commit_after>#include <iostream>
#include "subprocess.hpp"
#include <cstring>

// Note: this works even for ffmpeg with image2pipe to get err and out stream!
int manual_subprocess(const char* const* cmd)
{
	struct subprocess_s process;
	if(subprocess_create(cmd, subprocess_option_enable_async | subprocess_option_inherit_environment | subprocess_option_no_window, &process) != 0)
		return -1;

	const int nchars = 128, nerrchars = nchars * 2;
	char buf[nchars], errbuf[nerrchars];
	memset(buf, '\0', nchars);
	memset(errbuf, '\0', nerrchars);
	int ret2 = subprocess_read_stderr(&process, errbuf, nerrchars);
	if(ret2 == 0)
	{
		std::cout << "subprocess_read_stderr failure." << std::endl;
		return -1;
	}
	std::cout << "err ret:" << ret2 << std::endl;
	std::cout << "errbuf:" << errbuf << std::endl;
	int ret = subprocess_read_stdout(&process, buf, nchars); // struct subprocess_s *const process, char *const buffer,unsigned size);
	if(ret == 0) // TODO: this handling is missing in struct initialization for SPREAD
	{
		std::cout << "subprocess_read_stdout failure." << std::endl;
		return -1;
	}
	std::cout << "out ret:" << ret << std::endl;
	std::cout << "out buf:" << buf << std::endl;
	subprocess_destroy(&process);
	return 0;
}

int manual_subprocess_class(const char* const* cmd)
{
    Subprocess sp{cmd};

	const int nchars = 128, nerrchars = nchars * 2;
	char buf[nchars], errbuf[nerrchars];
	memset(buf, '\0', nchars);
	memset(errbuf, '\0', nerrchars);
	int ret2 = sp.read_from_stderr(errbuf, nerrchars);
	if(ret2 == 0)
	{
		std::cout << "subprocess_read_stderr completion of process, no data read." << std::endl;
		return -1;
	}
	std::cout << "err ret:" << ret2 << std::endl;
	std::cout << "errbuf:" << errbuf << std::endl;
	int ret = sp.read_from_stdout(buf, nchars); // struct subprocess_s *const process, char *const buffer,unsigned size);
	if(ret == 0) // TODO: this handling is missing in struct initialization for SPREAD
	{
		std::cout << "subprocess_read_stdout completion of process, no data read." << std::endl;
		return -1;
	}
	std::cout << "out ret:" << ret << std::endl;
	std::cout << "out buf:" << buf << std::endl;
	return 0;
}

int main(int argc,char** argv)
{
    std::cout << "Hello, world" << std::endl;
    //const char* cmd[]={"/usr/bin/ffmpeg",0}; // works if don't use errstream
	//const char *const cmd[] = {"/usr/bin/ffmpeg", "-v","24","-pix_fmts", 0};
    const char* cmd[] = {"/usr/bin/ffmpeg", "-i", "test.mp4", "-pix_fmt", "rgba", "-vcodec", "rawvideo", "-f", "rawvideo", "-", 0};

	manual_subprocess_class(cmd);

    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Hamburg University of Applied Sciences (HAW)
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @ingroup cpp11-compat
 * @{
 *
 * @file
 * @brief   C++11 condition variable drop in replacement
 *
 * @author  Raphael Hiesgen <raphael.hiesgen (at) haw-hamburg.de>
 *
 * @}
 */

#include <cstdio>
#include <stdexcept>
#include <system_error>

#include "irq.h"
#include "sched.h"
#include "vtimer.h"
#include "priority_queue.h"

#include "riot/condition_variable.hpp"

using namespace std::chrono;

namespace riot {

condition_variable::~condition_variable() { m_queue.first = NULL; }

void condition_variable::notify_one() noexcept {
  unsigned old_state = disableIRQ();
  priority_queue_node_t* head = priority_queue_remove_head(&m_queue);
  int other_prio = -1;
  if (head != NULL) {
    tcb_t* other_thread = (tcb_t*)sched_threads[head->data];
    if (other_thread) {
      other_prio = other_thread->priority;
      sched_set_status(other_thread, STATUS_PENDING);
    }
    head->data = -1u;
  }
  restoreIRQ(old_state);
  if (other_prio >= 0) {
    sched_switch(other_prio);
  }
}

void condition_variable::notify_all() noexcept {
  unsigned old_state = disableIRQ();
  int other_prio = -1;
  while (true) {
    priority_queue_node_t* head = priority_queue_remove_head(&m_queue);
    if (head == NULL) {
      break;
    }
    tcb_t* other_thread = (tcb_t*)sched_threads[head->data];
    if (other_thread) {
      auto max_prio
        = [](int a, int b) { return (a < 0) ? b : ((a < b) ? a : b); };
      other_prio = max_prio(other_prio, other_thread->priority);
      sched_set_status(other_thread, STATUS_PENDING);
    }
    head->data = -1u;
  }
  restoreIRQ(old_state);
  if (other_prio >= 0) {
    sched_switch(other_prio);
  }
}

void condition_variable::wait(unique_lock<mutex>& lock) noexcept {
  if (!lock.owns_lock()) {
    throw std::system_error(
      std::make_error_code(std::errc::operation_not_permitted),
      "Mutex not locked.");
  }
  priority_queue_node_t n;
  n.priority = sched_active_thread->priority;
  n.data = sched_active_pid;
  n.next = NULL;
  // the signaling thread may not hold the mutex, the queue is not thread safe
  unsigned old_state = disableIRQ();
  priority_queue_add(&m_queue, &n);
  restoreIRQ(old_state);
  mutex_unlock_and_sleep(lock.mutex()->native_handle());
  if (n.data != -1u) {
    // on signaling n.data is set to -1u
    // if it isn't set, then the wakeup is either spurious or a timer wakeup
    old_state = disableIRQ();
    priority_queue_remove(&m_queue, &n);
    restoreIRQ(old_state);
  }
  mutex_lock(lock.mutex()->native_handle());
}

cv_status condition_variable::wait_until(unique_lock<mutex>& lock,
                                         const time_point& timeout_time) {
  vtimer_t timer;
  // todo: use function to wait for absolute timepoint once available
  timex_t before;
  vtimer_now(&before);
  auto diff = timex_sub(timeout_time.native_handle(), before);
  vtimer_set_wakeup(&timer, diff, sched_active_pid);
  wait(lock);
  timex_t after;
  vtimer_now(&after);
  vtimer_remove(&timer);
  auto cmp = timex_cmp(after, timeout_time.native_handle());
  return cmp < 1 ? cv_status::no_timeout : cv_status::timeout;
}

} // namespace riot
<commit_msg>sys/cpp11-compat: condition variable: fix includes<commit_after>/*
 * Copyright (C) 2015 Hamburg University of Applied Sciences (HAW)
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @ingroup cpp11-compat
 * @{
 *
 * @file
 * @brief   C++11 condition variable drop in replacement
 *
 * @author  Raphael Hiesgen <raphael.hiesgen (at) haw-hamburg.de>
 *
 * @}
 */

#include <stdexcept>
#include <system_error>

#include "irq.h"
#include "sched.h"
#include "timex.h"
#include "vtimer.h"
#include "priority_queue.h"

#include "riot/condition_variable.hpp"

using namespace std::chrono;

namespace riot {

condition_variable::~condition_variable() { m_queue.first = NULL; }

void condition_variable::notify_one() noexcept {
  unsigned old_state = disableIRQ();
  priority_queue_node_t* head = priority_queue_remove_head(&m_queue);
  int other_prio = -1;
  if (head != NULL) {
    tcb_t* other_thread = (tcb_t*)sched_threads[head->data];
    if (other_thread) {
      other_prio = other_thread->priority;
      sched_set_status(other_thread, STATUS_PENDING);
    }
    head->data = -1u;
  }
  restoreIRQ(old_state);
  if (other_prio >= 0) {
    sched_switch(other_prio);
  }
}

void condition_variable::notify_all() noexcept {
  unsigned old_state = disableIRQ();
  int other_prio = -1;
  while (true) {
    priority_queue_node_t* head = priority_queue_remove_head(&m_queue);
    if (head == NULL) {
      break;
    }
    tcb_t* other_thread = (tcb_t*)sched_threads[head->data];
    if (other_thread) {
      auto max_prio
        = [](int a, int b) { return (a < 0) ? b : ((a < b) ? a : b); };
      other_prio = max_prio(other_prio, other_thread->priority);
      sched_set_status(other_thread, STATUS_PENDING);
    }
    head->data = -1u;
  }
  restoreIRQ(old_state);
  if (other_prio >= 0) {
    sched_switch(other_prio);
  }
}

void condition_variable::wait(unique_lock<mutex>& lock) noexcept {
  if (!lock.owns_lock()) {
    throw std::system_error(
      std::make_error_code(std::errc::operation_not_permitted),
      "Mutex not locked.");
  }
  priority_queue_node_t n;
  n.priority = sched_active_thread->priority;
  n.data = sched_active_pid;
  n.next = NULL;
  // the signaling thread may not hold the mutex, the queue is not thread safe
  unsigned old_state = disableIRQ();
  priority_queue_add(&m_queue, &n);
  restoreIRQ(old_state);
  mutex_unlock_and_sleep(lock.mutex()->native_handle());
  if (n.data != -1u) {
    // on signaling n.data is set to -1u
    // if it isn't set, then the wakeup is either spurious or a timer wakeup
    old_state = disableIRQ();
    priority_queue_remove(&m_queue, &n);
    restoreIRQ(old_state);
  }
  mutex_lock(lock.mutex()->native_handle());
}

cv_status condition_variable::wait_until(unique_lock<mutex>& lock,
                                         const time_point& timeout_time) {
  vtimer_t timer;
  // todo: use function to wait for absolute timepoint once available
  timex_t before;
  vtimer_now(&before);
  auto diff = timex_sub(timeout_time.native_handle(), before);
  vtimer_set_wakeup(&timer, diff, sched_active_pid);
  wait(lock);
  timex_t after;
  vtimer_now(&after);
  vtimer_remove(&timer);
  auto cmp = timex_cmp(after, timeout_time.native_handle());
  return cmp < 1 ? cv_status::no_timeout : cv_status::timeout;
}

} // namespace riot
<|endoftext|>