<commit_before>/* Copyright (c) 2017, CNRS-LAAS
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.

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. */

#include <pybind11/pybind11.h>

#include <pybind11/stl.h> // for conversions between c++ and python collections
#include <pybind11/numpy.h> // support for numpy arrays
#include "core/structures/trajectory.h"
#include "raster.h"
#include "vns/factory.h"

namespace py = pybind11;

/** Converts a numpy array to a vector */
template<class T>
std::vector<T> as_vector(py::array_t<T, py::array::c_style | py::array::forcecast> array) {
    std::vector<T> data(array.size());
    for(ssize_t x=0; x<array.shape(0); x++) {
        for(ssize_t y=0; y<array.shape(1); y++) {
            data[x + y*array.shape(0)] = *(array.data(x, y));
        }
    }
    return data;
}

/** Converts a vector to a 2D numpy array. */
template<class T>
py::array_t<T> as_nparray(std::vector<T> vec, size_t x_width, size_t y_height) {
    ASSERT(vec.size() == x_width * y_height)
    py::array_t<T, py::array::c_style | py::array::forcecast> array(std::vector<size_t> {x_width, y_height});
    auto s_x_width = static_cast<ssize_t>(x_width);
    auto s_y_height = static_cast<ssize_t>(y_height);
    for(ssize_t x=0; x<s_x_width; x++) {
        for (ssize_t y = 0; y < s_y_height; y++) {
            *(array.mutable_data(x, y)) = vec[x + y*x_width];
        }
    }
    return array;
}

PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);

PYBIND11_MODULE(uav_planning, m) {
    m.doc() = "Python module for UAV trajectory planning";

    srand(0);

    py::class_<DRaster>(m, "DRaster")
            .def(py::init([](py::array_t<double, py::array::c_style | py::array::forcecast> arr,
                             double x_offset, double y_offset, double cell_width) {
                return new DRaster(as_vector<double>(arr), arr.shape(0), arr.shape(1), x_offset, y_offset, cell_width);
            }))
            .def("as_numpy", [](DRaster& self) {
                return as_nparray<double>(self.data, self.x_width, self.y_height);
            })
            .def_readonly("x_offset", &DRaster::x_offset)
            .def_readonly("y_offset", &DRaster::y_offset)
            .def_readonly("cell_width", &DRaster::cell_width);

    py::class_<LRaster>(m, "LRaster")
            .def(py::init([](py::array_t<long, py::array::c_style | py::array::forcecast> arr,
                             double x_offset, double y_offset, double cell_width) {
                return new LRaster(as_vector<long>(arr), arr.shape(0), arr.shape(1), x_offset, y_offset, cell_width);
            }))
            .def("as_numpy", [](LRaster& self) {
                return as_nparray<long>(self.data, self.x_width, self.y_height);
            })
            .def_readonly("x_offset", &LRaster::x_offset)
            .def_readonly("y_offset", &LRaster::y_offset)
            .def_readonly("cell_width", &LRaster::cell_width);

    py::class_<TimeWindow>(m, "TimeWindow")
            .def(py::init<const double, const double>(),
                 py::arg("start"), py::arg("end"))
            .def_readonly("start", &TimeWindow::start)
            .def_readonly("end", &TimeWindow::end)
            .def("__repr__",
                 [](const TimeWindow &tw) {
                     std::stringstream repr;
                     repr << "TimeWindow(" << tw.start << ", " << tw.end << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](TimeWindow &self) {
                return py::make_tuple(self.start, self.end);
            } );

    py::class_<Cell>(m, "Cell")
            .def(py::init<const size_t, const size_t>(),
                 py::arg("x"), py::arg("y"))
            .def_readonly("x", &Cell::x)
            .def_readonly("y", &Cell::y)
            .def("__repr__",
                 [](const Cell &c) {
                     std::stringstream repr;
                     repr << "Cell(" << c.x << ", " << c.y << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](Cell &self) {
                return py::make_tuple(self.x, self.y);
            } );

    py::class_<Position>(m, "Position2d")
            .def(py::init<double, double>(),
                 py::arg("x"), py::arg("y"))
            .def_readonly("x", &Position::x)
            .def_readonly("y", &Position::y)
            .def("__repr__",
                 [](const Position &p) {
                     std::stringstream repr;
                     repr << "Position2d(" << p.x << ", " << p.y << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](Position &self) {
                return py::make_tuple(self.x, self.y);
            } );

    py::class_<Position3d>(m, "Position")
            .def(py::init<double, double, double>(),
                 py::arg("x"), py::arg("y"), py::arg("z"))
            .def_readonly("x", &Position3d::x)
            .def_readonly("y", &Position3d::y)
            .def_readonly("z", &Position3d::z)
            .def("__repr__",
                 [](const Position3d &p) {
                     std::stringstream repr;
                     repr << "Position(" << p.x << ", " << p.y << ", " << p.z << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](Position3d &self) {
                return py::make_tuple(self.x, self.y, self.z);
            } );

    py::class_<PositionTime>(m, "Position2dTime")
            .def(py::init<Position, double>(),
                 py::arg("point"), py::arg("time"))
            .def_readonly("pt", &PositionTime::pt)
            .def_readonly("y", &PositionTime::time)
            .def("__repr__",
                 [](const PositionTime &p) {
                     std::stringstream repr;
                     repr << "Position2dTime(" << p.pt.x << ", " << p.pt.y << ", " << p.time << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](PositionTime &self) {
                return py::make_tuple(py::make_tuple(self.pt.x, self.pt.y), self.time);
            } );

    py::class_<Position3dTime>(m, "PositionTime")
            .def(py::init<Position3d, double>(),
                 py::arg("point"), py::arg("time"))
            .def_readonly("pt", &Position3dTime::pt)
            .def_readonly("y", &Position3dTime::time)
            .def("__repr__",
                 [](const Position3dTime &p) {
                     std::stringstream repr;
                     repr << "PositionTime(" << p.pt.x << ", " << p.pt.y << ", " << p.pt.z << ", " << p.time << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](Position3dTime &self) {
                return py::make_tuple(py::make_tuple(self.pt.x, self.pt.y, self.pt.z), self.time);
            } );

    py::class_<FireData>(m, "FireData")
            .def(py::init<DRaster&, DiscreteDRaster&>(), py::arg("ignitions"), py::arg("elevation"))
            .def_readonly("ignitions", &FireData::ignitions)
            .def_readonly("traversal_end", &FireData::traversal_end)
            .def_readonly("propagation_directions", &FireData::propagation_directions)
            .def_readonly("elevation", &FireData::elevation);
//            .def_readonly_static("isochrone_timespan", &FireData::isochrone_timespan)
//            .def_readonly("isochrones", &FireData::isochrones);

    py::class_<Waypoint3d>(m, "Waypoint")
            .def(py::init<const double, const double, const double, const double>(),
                 py::arg("x"), py::arg("y"), py::arg("z"), py::arg("direction"))
            .def_readonly("x", &Waypoint3d::x)
            .def_readonly("y", &Waypoint3d::y)
            .def_readonly("z", &Waypoint3d::z)
            .def_readonly("dir", &Waypoint3d::dir)
            .def("__repr__", &Waypoint3d::to_string);

    py::class_<Segment3d>(m, "Segment")
            .def(py::init<const Waypoint3d, const double>())
            .def(py::init<const Waypoint3d, const Waypoint3d>())
            .def_readonly("start", &Segment3d::start)
            .def_readonly("end", &Segment3d::end)
            .def_readonly("length", &Segment3d::length)
            .def("__repr__", &Segment3d::to_string);

    py::class_<UAV>(m, "UAV")
            .def(py::init<const double, const double, const double>())
            .def_readonly("min_turn_radius", &UAV::min_turn_radius)
            .def_readonly("max_air_speed", &UAV::max_air_speed)
            .def_readonly("max_pitch_angle", &UAV::max_pitch_angle)
            .def("travel_distance", (double (UAV::*)(const Waypoint3d &, const Waypoint3d &) const)&UAV::travel_distance, py::arg("origin"), py::arg("destination"))
            .def("travel_distance", (double (UAV::*)(const Waypoint &, const Waypoint &) const)&UAV::travel_distance, py::arg("origin"), py::arg("destination"))
            .def("travel_time", (double (UAV::*)(const Waypoint3d &, const Waypoint3d &) const)&UAV::travel_time, py::arg("origin"), py::arg("destination"))
            .def("travel_time", (double (UAV::*)(const Waypoint &, const Waypoint &) const)&UAV::travel_time, py::arg("origin"), py::arg("destination"));

    py::class_<Trajectory>(m, "Trajectory")
            .def(py::init<const TrajectoryConfig&>())
            .def_readonly("conf", &Trajectory::conf)
            .def("start_time", (double (Trajectory::*)() const)&Trajectory::start_time)
            .def("end_time", (double (Trajectory::*)() const)&Trajectory::end_time)
            .def_readonly("segments", &Trajectory::traj)
            .def("length", &Trajectory::length)
            .def("duration", &Trajectory::duration)
            .def("as_waypoints", &Trajectory::as_waypoints)
            .def("sampled", &Trajectory::sampled, py::arg("step_size") = 1)
            .def("with_waypoint_at_end", &Trajectory::with_waypoint_at_end)
            .def("__repr__", &Trajectory::to_string);

    py::class_<TrajectoryConfig>(m, "TrajectoryConfig")
            .def(py::init<UAV, Waypoint3d, Waypoint3d, double, double>())
            .def_readonly("uav", &TrajectoryConfig::uav)
            .def_readonly("max_flight_time", &TrajectoryConfig::max_flight_time)
            .def_static("build", [](UAV uav, double start_time, double max_flight_time) -> TrajectoryConfig {
                return TrajectoryConfig(uav, start_time, max_flight_time);
            }, "Constructor", py::arg("uav"), py::arg("start_time") = 0,
                        py::arg("max_flight_time") = std::numeric_limits<double>::max());

    py::class_<Plan>(m, "Plan")
            .def("trajectories", [](Plan& self) { return self.core.trajectories; })
            .def("utility", &Plan::utility)
            .def("duration", &Plan::duration)
            .def_readonly("firedata", &Plan::firedata)
            .def("observations", &Plan::observations);

    py::class_<SearchResult>(m, "SearchResult")
            .def("initial_plan", &SearchResult::initial)
            .def("final_plan", &SearchResult::final)
            .def_readonly("intermediate_plans", &SearchResult::intermediate_plans)
            .def("metadata", [](SearchResult &self) { return self.metadata.dump(); } );

    m.def("plan_vns", [](vector<TrajectoryConfig> configs, DRaster ignitions, DRaster elevation, const std::string& json_conf) -> SearchResult {
        auto time = []() {
            struct timeval tp;
            gettimeofday(&tp, NULL);
            return (double) tp.tv_sec + ((double)(tp.tv_usec / 1000) /1000.);
        };
        json conf = json::parse(json_conf);
        const double min_time = conf["min_time"];
        const double max_time = conf["max_time"];
        const size_t save_every = conf["save_every"];
        const bool save_improvements = conf["save_improvements"];
        const size_t discrete_elevation_interval = conf["discrete_elevation_interval"];

        printf("Processing firedata data\n");
        double preprocessing_start = time();
        shared_ptr<FireData> fire_data;
        if (discrete_elevation_interval > 0) {
            fire_data = make_shared<FireData>(ignitions, DiscreteDRaster(elevation, discrete_elevation_interval));
        } else {
            fire_data = make_shared<FireData>(ignitions, elevation);
        }
        double preprocessing_end = time();

        printf("Building initial plan\n");
        Plan p(configs, fire_data, TimeWindow{min_time, max_time});

        printf("Planning\n");
        auto vns = vns::build_from_config(conf["vns"].dump());
        const double planning_start = time();
        auto res = vns->search(p, 0, save_every, save_improvements);
        const double planning_end = time();
        printf("Plan found\n");
        res.metadata["planning_time"] = planning_end - planning_start;
        res.metadata["preprocessing_time"] = preprocessing_end - preprocessing_start;
        res.metadata["configuration"] = conf;
        return res;
    }, py::arg("trajectory_configs"), py::arg("ignitions"), py::arg("elevation"), py::arg("json_conf"),
          py::call_guard<py::gil_scoped_release>());
}
<commit_msg>Expose UAV.path_sampling in python<commit_after>/* Copyright (c) 2017, CNRS-LAAS
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.

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. */

#include <pybind11/pybind11.h>

#include <pybind11/stl.h> // for conversions between c++ and python collections
#include <pybind11/numpy.h> // support for numpy arrays
#include "core/structures/trajectory.h"
#include "raster.h"
#include "vns/factory.h"

namespace py = pybind11;

/** Converts a numpy array to a vector */
template<class T>
std::vector<T> as_vector(py::array_t<T, py::array::c_style | py::array::forcecast> array) {
    std::vector<T> data(array.size());
    for(ssize_t x=0; x<array.shape(0); x++) {
        for(ssize_t y=0; y<array.shape(1); y++) {
            data[x + y*array.shape(0)] = *(array.data(x, y));
        }
    }
    return data;
}

/** Converts a vector to a 2D numpy array. */
template<class T>
py::array_t<T> as_nparray(std::vector<T> vec, size_t x_width, size_t y_height) {
    ASSERT(vec.size() == x_width * y_height)
    py::array_t<T, py::array::c_style | py::array::forcecast> array(std::vector<size_t> {x_width, y_height});
    auto s_x_width = static_cast<ssize_t>(x_width);
    auto s_y_height = static_cast<ssize_t>(y_height);
    for(ssize_t x=0; x<s_x_width; x++) {
        for (ssize_t y = 0; y < s_y_height; y++) {
            *(array.mutable_data(x, y)) = vec[x + y*x_width];
        }
    }
    return array;
}

PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);

PYBIND11_MODULE(uav_planning, m) {
    m.doc() = "Python module for UAV trajectory planning";

    srand(0);

    py::class_<DRaster>(m, "DRaster")
            .def(py::init([](py::array_t<double, py::array::c_style | py::array::forcecast> arr,
                             double x_offset, double y_offset, double cell_width) {
                return new DRaster(as_vector<double>(arr), arr.shape(0), arr.shape(1), x_offset, y_offset, cell_width);
            }))
            .def("as_numpy", [](DRaster& self) {
                return as_nparray<double>(self.data, self.x_width, self.y_height);
            })
            .def_readonly("x_offset", &DRaster::x_offset)
            .def_readonly("y_offset", &DRaster::y_offset)
            .def_readonly("cell_width", &DRaster::cell_width);

    py::class_<LRaster>(m, "LRaster")
            .def(py::init([](py::array_t<long, py::array::c_style | py::array::forcecast> arr,
                             double x_offset, double y_offset, double cell_width) {
                return new LRaster(as_vector<long>(arr), arr.shape(0), arr.shape(1), x_offset, y_offset, cell_width);
            }))
            .def("as_numpy", [](LRaster& self) {
                return as_nparray<long>(self.data, self.x_width, self.y_height);
            })
            .def_readonly("x_offset", &LRaster::x_offset)
            .def_readonly("y_offset", &LRaster::y_offset)
            .def_readonly("cell_width", &LRaster::cell_width);

    py::class_<TimeWindow>(m, "TimeWindow")
            .def(py::init<const double, const double>(),
                 py::arg("start"), py::arg("end"))
            .def_readonly("start", &TimeWindow::start)
            .def_readonly("end", &TimeWindow::end)
            .def("__repr__",
                 [](const TimeWindow &tw) {
                     std::stringstream repr;
                     repr << "TimeWindow(" << tw.start << ", " << tw.end << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](TimeWindow &self) {
                return py::make_tuple(self.start, self.end);
            } );

    py::class_<Cell>(m, "Cell")
            .def(py::init<const size_t, const size_t>(),
                 py::arg("x"), py::arg("y"))
            .def_readonly("x", &Cell::x)
            .def_readonly("y", &Cell::y)
            .def("__repr__",
                 [](const Cell &c) {
                     std::stringstream repr;
                     repr << "Cell(" << c.x << ", " << c.y << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](Cell &self) {
                return py::make_tuple(self.x, self.y);
            } );

    py::class_<Position>(m, "Position2d")
            .def(py::init<double, double>(),
                 py::arg("x"), py::arg("y"))
            .def_readonly("x", &Position::x)
            .def_readonly("y", &Position::y)
            .def("__repr__",
                 [](const Position &p) {
                     std::stringstream repr;
                     repr << "Position2d(" << p.x << ", " << p.y << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](Position &self) {
                return py::make_tuple(self.x, self.y);
            } );

    py::class_<Position3d>(m, "Position")
            .def(py::init<double, double, double>(),
                 py::arg("x"), py::arg("y"), py::arg("z"))
            .def_readonly("x", &Position3d::x)
            .def_readonly("y", &Position3d::y)
            .def_readonly("z", &Position3d::z)
            .def("__repr__",
                 [](const Position3d &p) {
                     std::stringstream repr;
                     repr << "Position(" << p.x << ", " << p.y << ", " << p.z << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](Position3d &self) {
                return py::make_tuple(self.x, self.y, self.z);
            } );

    py::class_<PositionTime>(m, "Position2dTime")
            .def(py::init<Position, double>(),
                 py::arg("point"), py::arg("time"))
            .def_readonly("pt", &PositionTime::pt)
            .def_readonly("y", &PositionTime::time)
            .def("__repr__",
                 [](const PositionTime &p) {
                     std::stringstream repr;
                     repr << "Position2dTime(" << p.pt.x << ", " << p.pt.y << ", " << p.time << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](PositionTime &self) {
                return py::make_tuple(py::make_tuple(self.pt.x, self.pt.y), self.time);
            } );

    py::class_<Position3dTime>(m, "PositionTime")
            .def(py::init<Position3d, double>(),
                 py::arg("point"), py::arg("time"))
            .def_readonly("pt", &Position3dTime::pt)
            .def_readonly("y", &Position3dTime::time)
            .def("__repr__",
                 [](const Position3dTime &p) {
                     std::stringstream repr;
                     repr << "PositionTime(" << p.pt.x << ", " << p.pt.y << ", " << p.pt.z << ", " << p.time << ")";
                     return repr.str();
                 }
            )
            .def("as_tuple", [](Position3dTime &self) {
                return py::make_tuple(py::make_tuple(self.pt.x, self.pt.y, self.pt.z), self.time);
            } );

    py::class_<FireData>(m, "FireData")
            .def(py::init<DRaster&, DiscreteDRaster&>(), py::arg("ignitions"), py::arg("elevation"))
            .def_readonly("ignitions", &FireData::ignitions)
            .def_readonly("traversal_end", &FireData::traversal_end)
            .def_readonly("propagation_directions", &FireData::propagation_directions)
            .def_readonly("elevation", &FireData::elevation);
//            .def_readonly_static("isochrone_timespan", &FireData::isochrone_timespan)
//            .def_readonly("isochrones", &FireData::isochrones);

    py::class_<Waypoint3d>(m, "Waypoint")
            .def(py::init<const double, const double, const double, const double>(),
                 py::arg("x"), py::arg("y"), py::arg("z"), py::arg("direction"))
            .def_readonly("x", &Waypoint3d::x)
            .def_readonly("y", &Waypoint3d::y)
            .def_readonly("z", &Waypoint3d::z)
            .def_readonly("dir", &Waypoint3d::dir)
            .def("__repr__", &Waypoint3d::to_string);

    py::class_<Segment3d>(m, "Segment")
            .def(py::init<const Waypoint3d, const double>())
            .def(py::init<const Waypoint3d, const Waypoint3d>())
            .def_readonly("start", &Segment3d::start)
            .def_readonly("end", &Segment3d::end)
            .def_readonly("length", &Segment3d::length)
            .def("__repr__", &Segment3d::to_string);

    py::class_<UAV>(m, "UAV")
            .def(py::init<const double, const double, const double>())
            .def_readonly("min_turn_radius", &UAV::min_turn_radius)
            .def_readonly("max_air_speed", &UAV::max_air_speed)
            .def_readonly("max_pitch_angle", &UAV::max_pitch_angle)
            .def("travel_distance", (double (UAV::*)(const Waypoint3d &, const Waypoint3d &) const)
                    &UAV::travel_distance, py::arg("origin"), py::arg("destination"))
            .def("travel_distance", (double (UAV::*)(const Waypoint &, const Waypoint &) const)
                    &UAV::travel_distance, py::arg("origin"), py::arg("destination"))
            .def("travel_time", (double (UAV::*)(const Waypoint3d &, const Waypoint3d &) const)
                    &UAV::travel_time, py::arg("origin"), py::arg("destination"))
            .def("travel_time", (double (UAV::*)(const Waypoint &, const Waypoint &) const)
                    &UAV::travel_time, py::arg("origin"), py::arg("destination"))
            .def("path_sampling", (std::vector<Waypoint3d> (UAV::*)(const Waypoint3d &, const Waypoint3d &, const double) const)
                    &UAV::path_sampling, py::arg("origin"), py::arg("destination"), py::arg("step_size"));

    py::class_<Trajectory>(m, "Trajectory")
            .def(py::init<const TrajectoryConfig&>())
            .def_readonly("conf", &Trajectory::conf)
            .def("start_time", (double (Trajectory::*)() const)&Trajectory::start_time)
            .def("end_time", (double (Trajectory::*)() const)&Trajectory::end_time)
            .def_readonly("segments", &Trajectory::traj)
            .def("length", &Trajectory::length)
            .def("duration", &Trajectory::duration)
            .def("as_waypoints", &Trajectory::as_waypoints)
            .def("sampled", &Trajectory::sampled, py::arg("step_size") = 1)
            .def("with_waypoint_at_end", &Trajectory::with_waypoint_at_end)
            .def("__repr__", &Trajectory::to_string);

    py::class_<TrajectoryConfig>(m, "TrajectoryConfig")
            .def(py::init<UAV, Waypoint3d, Waypoint3d, double, double>())
            .def_readonly("uav", &TrajectoryConfig::uav)
            .def_readonly("max_flight_time", &TrajectoryConfig::max_flight_time)
            .def_static("build", [](UAV uav, double start_time, double max_flight_time) -> TrajectoryConfig {
                return TrajectoryConfig(uav, start_time, max_flight_time);
            }, "Constructor", py::arg("uav"), py::arg("start_time") = 0,
                        py::arg("max_flight_time") = std::numeric_limits<double>::max());

    py::class_<Plan>(m, "Plan")
            .def("trajectories", [](Plan& self) { return self.core.trajectories; })
            .def("utility", &Plan::utility)
            .def("duration", &Plan::duration)
            .def_readonly("firedata", &Plan::firedata)
            .def("observations", &Plan::observations);

    py::class_<SearchResult>(m, "SearchResult")
            .def("initial_plan", &SearchResult::initial)
            .def("final_plan", &SearchResult::final)
            .def_readonly("intermediate_plans", &SearchResult::intermediate_plans)
            .def("metadata", [](SearchResult &self) { return self.metadata.dump(); } );

    m.def("plan_vns", [](vector<TrajectoryConfig> configs, DRaster ignitions, DRaster elevation, const std::string& json_conf) -> SearchResult {
        auto time = []() {
            struct timeval tp;
            gettimeofday(&tp, NULL);
            return (double) tp.tv_sec + ((double)(tp.tv_usec / 1000) /1000.);
        };
        json conf = json::parse(json_conf);
        const double min_time = conf["min_time"];
        const double max_time = conf["max_time"];
        const size_t save_every = conf["save_every"];
        const bool save_improvements = conf["save_improvements"];
        const size_t discrete_elevation_interval = conf["discrete_elevation_interval"];

        printf("Processing firedata data\n");
        double preprocessing_start = time();
        shared_ptr<FireData> fire_data;
        if (discrete_elevation_interval > 0) {
            fire_data = make_shared<FireData>(ignitions, DiscreteDRaster(elevation, discrete_elevation_interval));
        } else {
            fire_data = make_shared<FireData>(ignitions, elevation);
        }
        double preprocessing_end = time();

        printf("Building initial plan\n");
        Plan p(configs, fire_data, TimeWindow{min_time, max_time});

        printf("Planning\n");
        auto vns = vns::build_from_config(conf["vns"].dump());
        const double planning_start = time();
        auto res = vns->search(p, 0, save_every, save_improvements);
        const double planning_end = time();
        printf("Plan found\n");
        res.metadata["planning_time"] = planning_end - planning_start;
        res.metadata["preprocessing_time"] = preprocessing_end - preprocessing_start;
        res.metadata["configuration"] = conf;
        return res;
    }, py::arg("trajectory_configs"), py::arg("ignitions"), py::arg("elevation"), py::arg("json_conf"),
          py::call_guard<py::gil_scoped_release>());
}
<|endoftext|>


<commit_before>//===--- XPCService.cpp ---------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "sourcekitd/Internal-XPC.h"
#include "sourcekitd/Logging.h"

#include "SourceKit/Core/LLVM.h"
#include "SourceKit/Support/Concurrency.h"
#include "SourceKit/Support/UIdent.h"
#include "SourceKit/Support/Logging.h"

#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Threading.h"

#include <xpc/xpc.h>

using namespace SourceKit;
using namespace sourcekitd;

static xpc_connection_t MainConnection = nullptr;

void sourcekitd::postNotification(sourcekitd_response_t Notification) {
  xpc_connection_t peer = MainConnection;
  if (!peer)
    goto done;

  {
    xpc_object_t contents = xpc_array_create(nullptr, 0);
    xpc_array_set_uint64(contents, XPC_ARRAY_APPEND,
                         (uint64_t)xpc::Message::Notification);
    xpc_array_set_value(contents, XPC_ARRAY_APPEND, Notification);

    xpc_object_t msg = xpc_dictionary_create(nullptr, nullptr, 0);
    xpc_dictionary_set_value(msg, xpc::KeyInternalMsg, contents);
    xpc_release(contents);

    xpc_connection_send_message(peer, msg);
    xpc_release(msg);
  }

done:
  // The function accepted ownership.
  xpc_release(Notification);
}

namespace {
/// \brief Associates sourcekitd_uid_t to a UIdent.
class SKUIDToUIDMap {
  typedef llvm::DenseMap<void *, UIdent> MapTy;
  MapTy Map;
  WorkQueue Queue{ WorkQueue::Dequeuing::Concurrent, "UIDMap" };

public:
  UIdent get(sourcekitd_uid_t SKDUID);
  void set(sourcekitd_uid_t SKDUID, UIdent UID);
};
}

static SKUIDToUIDMap UIDMap;

sourcekitd_uid_t sourcekitd::SKDUIDFromUIdent(UIdent UID) {
  if (void *Tag = UID.getTag())
    return reinterpret_cast<sourcekitd_uid_t>(Tag);

  // FIXME: The following should run in the synchronous dispatch queue of the
  // connection. But does it matter, since if MainConnection is null or gets
  // destroyed it means the client crashed ?
  xpc_connection_t peer = MainConnection;
  if (!peer)
    return nullptr;

  xpc_object_t contents = xpc_array_create(nullptr, 0);
  xpc_array_set_uint64(contents, XPC_ARRAY_APPEND,
                       (uint64_t)xpc::Message::UIDSynchronization);
  xpc_array_set_string(contents, XPC_ARRAY_APPEND, UID.c_str());

  xpc_object_t msg = xpc_dictionary_create(nullptr, nullptr,  0);
  xpc_dictionary_set_value(msg, xpc::KeyInternalMsg, contents);
  xpc_release(contents);

  xpc_object_t reply = xpc_connection_send_message_with_reply_sync(peer, msg);
  xpc_release(msg);
  if (xpc_get_type(reply) == XPC_TYPE_ERROR) {
    xpc_release(reply);
    return nullptr;
  }

  assert(xpc_get_type(reply) == XPC_TYPE_DICTIONARY);
  uint64_t val = xpc_dictionary_get_uint64(reply, xpc::KeyMsgResponse);
  xpc_release(reply);

  sourcekitd_uid_t skduid = sourcekitd_uid_t(val);
  UID.setTag(skduid);
  UIDMap.set(skduid, UID);
  return skduid;
}

UIdent sourcekitd::UIdentFromSKDUID(sourcekitd_uid_t SKDUID) {
  // This should be used only for debugging/logging purposes.

  UIdent UID = UIDMap.get(SKDUID);
  if (UID.isValid())
    return UID;

  xpc_connection_t Peer = MainConnection;
  if (!Peer)
    return UIdent();

  xpc_object_t contents = xpc_array_create(nullptr, 0);
  xpc_array_set_uint64(contents, XPC_ARRAY_APPEND,
                       (uint64_t)xpc::Message::UIDSynchronization);
  xpc_array_set_uint64(contents, XPC_ARRAY_APPEND, uintptr_t(SKDUID));

  xpc_object_t msg = xpc_dictionary_create(nullptr, nullptr,  0);
  xpc_dictionary_set_value(msg, xpc::KeyInternalMsg, contents);
  xpc_release(contents);

  xpc_object_t reply = xpc_connection_send_message_with_reply_sync(Peer, msg);
  xpc_release(msg);
  if (xpc_get_type(reply) == XPC_TYPE_ERROR) {
    xpc_release(reply);
    return UIdent();
  }

  assert(xpc_get_type(reply) == XPC_TYPE_DICTIONARY);
  const char *Str = xpc_dictionary_get_string(reply, xpc::KeyMsgResponse);

  UID = UIdent(Str);
  UID.setTag(SKDUID);
  UIDMap.set(SKDUID, UID);

  xpc_release(reply);
  return UID;
}

void anchorForGetMainExecutableInXPCService() {}

namespace {
/// Responsible for replying to an XPC request.
class XPCResponder {
  xpc_connection_t Peer;
  xpc_object_t Event;
  bool Responded = false;

public:
  XPCResponder(xpc_object_t event, xpc_connection_t peer)
    : Peer(xpc_connection_t(xpc_retain(peer))), Event(xpc_retain(event)) {}

  ~XPCResponder() {
    if (!Responded) {
      LOG_WARN_FUNC("failed to respond to request");
      sendReply(createErrorRequestFailed("Internal error: no response was "
                                         "provided for the request"));
    }
    xpc_release(Event);
    xpc_release(Peer);
  }

  /// Accepts ownership of the response object.
  void sendReply(sourcekitd_response_t response) {
    if (Responded) {
      LOG_WARN_FUNC("tried to respond to an already handled request");
      return;
    }

    xpc_object_t reply = xpc_dictionary_create_reply(Event);
    xpc_dictionary_set_value(reply, xpc::KeyMsgResponse, response);
    xpc_release(response);

    xpc_connection_send_message(Peer, reply);
    xpc_release(reply);
    Responded = true;
  }
};
}

std::string sourcekitd::getRuntimeLibPath() {
  std::string MainExePath = llvm::sys::fs::getMainExecutable("sourcekit",
             reinterpret_cast<void *>(&anchorForGetMainExecutableInXPCService));
#ifdef SOURCEKIT_UNVERSIONED_FRAMEWORK_BUNDLE
  // MainExePath points to "lib/sourcekitd.framework/XPCServices/
  //                       SourceKitService.xpc/SourceKitService"
  const unsigned MainExeLibNestingLevel = 4;
#else
  // MainExePath points to "lib/sourcekitd.framework/Versions/Current/XPCServices/
  //                       SourceKitService.xpc/Contents/MacOS/SourceKitService"
  const unsigned MainExeLibNestingLevel = 8;
#endif

  // Get it to lib.
  StringRef Path = MainExePath;
  for (unsigned i = 0; i < MainExeLibNestingLevel; ++i)
    Path = llvm::sys::path::parent_path(Path);
  return Path;
}

static void sourcekitdServer_peer_event_handler(xpc_connection_t peer,
                                                xpc_object_t event) {
  xpc_type_t type = xpc_get_type(event);
  if (type == XPC_TYPE_ERROR) {
    if (event == XPC_ERROR_CONNECTION_INVALID) {
      // The client process on the other end of the connection has either
      // crashed or cancelled the connection. After receiving this error,
      // the connection is in an invalid state, and we do not need to
      // call xpc_connection_cancel().
      // No need to call sourcekitd::shutdown() since the process is going down
      // anyway, plus if we get a new connection before the process closes then
      // we will fail to re-initialize properly since the initialize call is at
      // main.
      xpc_transaction_end();
    } else if (event == XPC_ERROR_TERMINATION_IMMINENT) {
      // Handle per-connection termination cleanup.
      xpc_connection_cancel(peer);
    }

  } else {
    assert(type == XPC_TYPE_DICTIONARY);
    // Handle the message
    xpc_retain(event);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
    ^{
      xpc_object_t contents = xpc_dictionary_get_value(event, "msg");

      if (!contents) {
        // Ping back.
        contents = xpc_dictionary_get_value(event, "ping");
        assert(contents && "unexpected message");
        xpc_object_t reply = xpc_dictionary_create_reply(event);
        assert(reply);
        xpc_connection_send_message(peer, reply);
        xpc_release(reply);
        return;
      }

      auto Responder = std::make_shared<XPCResponder>(event, peer);
      xpc_release(event);

      assert(xpc_get_type(contents) == XPC_TYPE_ARRAY);
      sourcekitd_object_t req = xpc_array_get_value(contents, 0);
      sourcekitd::handleRequest(req,
        [Responder](sourcekitd_response_t response) {
          Responder->sendReply(response);
        });
    });
  }
}

static void getInitializationInfo(xpc_connection_t peer) {
  xpc_object_t contents = xpc_array_create(nullptr, 0);
  xpc_array_set_uint64(contents, XPC_ARRAY_APPEND,
                       (uint64_t)xpc::Message::Initialization);

  xpc_object_t msg = xpc_dictionary_create(nullptr, nullptr,  0);
  xpc_dictionary_set_value(msg, xpc::KeyInternalMsg, contents);
  xpc_release(contents);

  xpc_object_t reply = xpc_connection_send_message_with_reply_sync(peer, msg);
  xpc_release(msg);
  if (xpc_get_type(reply) == XPC_TYPE_ERROR) {
    xpc_release(reply);
    return;
  }

  assert(xpc_get_type(reply) == XPC_TYPE_DICTIONARY);
  uint64_t Delay = xpc_dictionary_get_uint64(reply, xpc::KeySemaEditorDelay);
  xpc_release(reply);

  if (Delay != 0) {
    llvm::SmallString<4> Buf;
    {
      llvm::raw_svector_ostream OS(Buf);
      OS << Delay;
    }
    setenv("SOURCEKIT_DELAY_SEMA_EDITOR", Buf.c_str(), /*overwrite=*/1);
  }
}

static void sourcekitdServer_event_handler(xpc_connection_t peer) {
  // Keep the service alive even when idle.
  xpc_transaction_begin();

  // By defaults, new connections will target the default dispatch
  // concurrent queue.
  xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
    sourcekitdServer_peer_event_handler(peer, event);
  });

  // Update the main connection
  xpc_retain(peer);
  if (MainConnection)
    xpc_release(MainConnection);
  MainConnection = peer;

  // This will tell the connection to begin listening for events. If you
  // have some other initialization that must be done asynchronously, then
  // you can defer this call until after that initialization is done.
  xpc_connection_resume(peer);

  dispatch_async(dispatch_get_main_queue(), ^{
    getInitializationInfo(MainConnection);
  });
}

static void fatal_error_handler(void *user_data, const std::string& reason,
                                bool gen_crash_diag) {
  // Write the result out to stderr avoiding errs() because raw_ostreams can
  // call report_fatal_error.
  fprintf(stderr, "SOURCEKITD SERVER FATAL ERROR: %s\n", reason.c_str());
  ::abort();
}

int main(int argc, const char *argv[]) {
  llvm::install_fatal_error_handler(fatal_error_handler, 0);
  sourcekitd::enableLogging("sourcekit-serv");
  sourcekitd::initialize();

  // Increase the file descriptor limit.
  // FIXME: Portability ?
  static const size_t FDLimit = 4096;
  struct rlimit l;
  if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
    if (l.rlim_cur < FDLimit) {
      l.rlim_cur = FDLimit;
      if (setrlimit(RLIMIT_NOFILE, &l) == 0) {
        LOG_INFO_FUNC(Low, "bumped file descriptor limit to " << FDLimit);
      } else {
        LOG_WARN_FUNC("setrlimit failed: " << llvm::sys::StrError());
      }
    }
  } else {
    LOG_WARN_FUNC("getrlimit failed: " << llvm::sys::StrError());
  }

  xpc_main(sourcekitdServer_event_handler);
  return 0;
}

UIdent SKUIDToUIDMap::get(sourcekitd_uid_t SKDUID) {
  UIdent UID;
  Queue.dispatchSync([&]{
    MapTy::iterator It = Map.find(SKDUID);
    if (It != Map.end())
      UID = It->second;
  });

  return UID;
}

void SKUIDToUIDMap::set(sourcekitd_uid_t SKDUID, UIdent UID) {
  Queue.dispatchBarrier([=]{
    this->Map[SKDUID] = UID;
  });
}
<commit_msg>[sourcekitd] In the fatal error handler, don't call abort() if gen_crash_diag is false<commit_after>//===--- XPCService.cpp ---------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "sourcekitd/Internal-XPC.h"
#include "sourcekitd/Logging.h"

#include "SourceKit/Core/LLVM.h"
#include "SourceKit/Support/Concurrency.h"
#include "SourceKit/Support/UIdent.h"
#include "SourceKit/Support/Logging.h"

#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Threading.h"

#include <xpc/xpc.h>

using namespace SourceKit;
using namespace sourcekitd;

static xpc_connection_t MainConnection = nullptr;

void sourcekitd::postNotification(sourcekitd_response_t Notification) {
  xpc_connection_t peer = MainConnection;
  if (!peer)
    goto done;

  {
    xpc_object_t contents = xpc_array_create(nullptr, 0);
    xpc_array_set_uint64(contents, XPC_ARRAY_APPEND,
                         (uint64_t)xpc::Message::Notification);
    xpc_array_set_value(contents, XPC_ARRAY_APPEND, Notification);

    xpc_object_t msg = xpc_dictionary_create(nullptr, nullptr, 0);
    xpc_dictionary_set_value(msg, xpc::KeyInternalMsg, contents);
    xpc_release(contents);

    xpc_connection_send_message(peer, msg);
    xpc_release(msg);
  }

done:
  // The function accepted ownership.
  xpc_release(Notification);
}

namespace {
/// \brief Associates sourcekitd_uid_t to a UIdent.
class SKUIDToUIDMap {
  typedef llvm::DenseMap<void *, UIdent> MapTy;
  MapTy Map;
  WorkQueue Queue{ WorkQueue::Dequeuing::Concurrent, "UIDMap" };

public:
  UIdent get(sourcekitd_uid_t SKDUID);
  void set(sourcekitd_uid_t SKDUID, UIdent UID);
};
}

static SKUIDToUIDMap UIDMap;

sourcekitd_uid_t sourcekitd::SKDUIDFromUIdent(UIdent UID) {
  if (void *Tag = UID.getTag())
    return reinterpret_cast<sourcekitd_uid_t>(Tag);

  // FIXME: The following should run in the synchronous dispatch queue of the
  // connection. But does it matter, since if MainConnection is null or gets
  // destroyed it means the client crashed ?
  xpc_connection_t peer = MainConnection;
  if (!peer)
    return nullptr;

  xpc_object_t contents = xpc_array_create(nullptr, 0);
  xpc_array_set_uint64(contents, XPC_ARRAY_APPEND,
                       (uint64_t)xpc::Message::UIDSynchronization);
  xpc_array_set_string(contents, XPC_ARRAY_APPEND, UID.c_str());

  xpc_object_t msg = xpc_dictionary_create(nullptr, nullptr,  0);
  xpc_dictionary_set_value(msg, xpc::KeyInternalMsg, contents);
  xpc_release(contents);

  xpc_object_t reply = xpc_connection_send_message_with_reply_sync(peer, msg);
  xpc_release(msg);
  if (xpc_get_type(reply) == XPC_TYPE_ERROR) {
    xpc_release(reply);
    return nullptr;
  }

  assert(xpc_get_type(reply) == XPC_TYPE_DICTIONARY);
  uint64_t val = xpc_dictionary_get_uint64(reply, xpc::KeyMsgResponse);
  xpc_release(reply);

  sourcekitd_uid_t skduid = sourcekitd_uid_t(val);
  UID.setTag(skduid);
  UIDMap.set(skduid, UID);
  return skduid;
}

UIdent sourcekitd::UIdentFromSKDUID(sourcekitd_uid_t SKDUID) {
  // This should be used only for debugging/logging purposes.

  UIdent UID = UIDMap.get(SKDUID);
  if (UID.isValid())
    return UID;

  xpc_connection_t Peer = MainConnection;
  if (!Peer)
    return UIdent();

  xpc_object_t contents = xpc_array_create(nullptr, 0);
  xpc_array_set_uint64(contents, XPC_ARRAY_APPEND,
                       (uint64_t)xpc::Message::UIDSynchronization);
  xpc_array_set_uint64(contents, XPC_ARRAY_APPEND, uintptr_t(SKDUID));

  xpc_object_t msg = xpc_dictionary_create(nullptr, nullptr,  0);
  xpc_dictionary_set_value(msg, xpc::KeyInternalMsg, contents);
  xpc_release(contents);

  xpc_object_t reply = xpc_connection_send_message_with_reply_sync(Peer, msg);
  xpc_release(msg);
  if (xpc_get_type(reply) == XPC_TYPE_ERROR) {
    xpc_release(reply);
    return UIdent();
  }

  assert(xpc_get_type(reply) == XPC_TYPE_DICTIONARY);
  const char *Str = xpc_dictionary_get_string(reply, xpc::KeyMsgResponse);

  UID = UIdent(Str);
  UID.setTag(SKDUID);
  UIDMap.set(SKDUID, UID);

  xpc_release(reply);
  return UID;
}

void anchorForGetMainExecutableInXPCService() {}

namespace {
/// Responsible for replying to an XPC request.
class XPCResponder {
  xpc_connection_t Peer;
  xpc_object_t Event;
  bool Responded = false;

public:
  XPCResponder(xpc_object_t event, xpc_connection_t peer)
    : Peer(xpc_connection_t(xpc_retain(peer))), Event(xpc_retain(event)) {}

  ~XPCResponder() {
    if (!Responded) {
      LOG_WARN_FUNC("failed to respond to request");
      sendReply(createErrorRequestFailed("Internal error: no response was "
                                         "provided for the request"));
    }
    xpc_release(Event);
    xpc_release(Peer);
  }

  /// Accepts ownership of the response object.
  void sendReply(sourcekitd_response_t response) {
    if (Responded) {
      LOG_WARN_FUNC("tried to respond to an already handled request");
      return;
    }

    xpc_object_t reply = xpc_dictionary_create_reply(Event);
    xpc_dictionary_set_value(reply, xpc::KeyMsgResponse, response);
    xpc_release(response);

    xpc_connection_send_message(Peer, reply);
    xpc_release(reply);
    Responded = true;
  }
};
}

std::string sourcekitd::getRuntimeLibPath() {
  std::string MainExePath = llvm::sys::fs::getMainExecutable("sourcekit",
             reinterpret_cast<void *>(&anchorForGetMainExecutableInXPCService));
#ifdef SOURCEKIT_UNVERSIONED_FRAMEWORK_BUNDLE
  // MainExePath points to "lib/sourcekitd.framework/XPCServices/
  //                       SourceKitService.xpc/SourceKitService"
  const unsigned MainExeLibNestingLevel = 4;
#else
  // MainExePath points to "lib/sourcekitd.framework/Versions/Current/XPCServices/
  //                       SourceKitService.xpc/Contents/MacOS/SourceKitService"
  const unsigned MainExeLibNestingLevel = 8;
#endif

  // Get it to lib.
  StringRef Path = MainExePath;
  for (unsigned i = 0; i < MainExeLibNestingLevel; ++i)
    Path = llvm::sys::path::parent_path(Path);
  return Path;
}

static void sourcekitdServer_peer_event_handler(xpc_connection_t peer,
                                                xpc_object_t event) {
  xpc_type_t type = xpc_get_type(event);
  if (type == XPC_TYPE_ERROR) {
    if (event == XPC_ERROR_CONNECTION_INVALID) {
      // The client process on the other end of the connection has either
      // crashed or cancelled the connection. After receiving this error,
      // the connection is in an invalid state, and we do not need to
      // call xpc_connection_cancel().
      // No need to call sourcekitd::shutdown() since the process is going down
      // anyway, plus if we get a new connection before the process closes then
      // we will fail to re-initialize properly since the initialize call is at
      // main.
      xpc_transaction_end();
    } else if (event == XPC_ERROR_TERMINATION_IMMINENT) {
      // Handle per-connection termination cleanup.
      xpc_connection_cancel(peer);
    }

  } else {
    assert(type == XPC_TYPE_DICTIONARY);
    // Handle the message
    xpc_retain(event);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
    ^{
      xpc_object_t contents = xpc_dictionary_get_value(event, "msg");

      if (!contents) {
        // Ping back.
        contents = xpc_dictionary_get_value(event, "ping");
        assert(contents && "unexpected message");
        xpc_object_t reply = xpc_dictionary_create_reply(event);
        assert(reply);
        xpc_connection_send_message(peer, reply);
        xpc_release(reply);
        return;
      }

      auto Responder = std::make_shared<XPCResponder>(event, peer);
      xpc_release(event);

      assert(xpc_get_type(contents) == XPC_TYPE_ARRAY);
      sourcekitd_object_t req = xpc_array_get_value(contents, 0);
      sourcekitd::handleRequest(req,
        [Responder](sourcekitd_response_t response) {
          Responder->sendReply(response);
        });
    });
  }
}

static void getInitializationInfo(xpc_connection_t peer) {
  xpc_object_t contents = xpc_array_create(nullptr, 0);
  xpc_array_set_uint64(contents, XPC_ARRAY_APPEND,
                       (uint64_t)xpc::Message::Initialization);

  xpc_object_t msg = xpc_dictionary_create(nullptr, nullptr,  0);
  xpc_dictionary_set_value(msg, xpc::KeyInternalMsg, contents);
  xpc_release(contents);

  xpc_object_t reply = xpc_connection_send_message_with_reply_sync(peer, msg);
  xpc_release(msg);
  if (xpc_get_type(reply) == XPC_TYPE_ERROR) {
    xpc_release(reply);
    return;
  }

  assert(xpc_get_type(reply) == XPC_TYPE_DICTIONARY);
  uint64_t Delay = xpc_dictionary_get_uint64(reply, xpc::KeySemaEditorDelay);
  xpc_release(reply);

  if (Delay != 0) {
    llvm::SmallString<4> Buf;
    {
      llvm::raw_svector_ostream OS(Buf);
      OS << Delay;
    }
    setenv("SOURCEKIT_DELAY_SEMA_EDITOR", Buf.c_str(), /*overwrite=*/1);
  }
}

static void sourcekitdServer_event_handler(xpc_connection_t peer) {
  // Keep the service alive even when idle.
  xpc_transaction_begin();

  // By defaults, new connections will target the default dispatch
  // concurrent queue.
  xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
    sourcekitdServer_peer_event_handler(peer, event);
  });

  // Update the main connection
  xpc_retain(peer);
  if (MainConnection)
    xpc_release(MainConnection);
  MainConnection = peer;

  // This will tell the connection to begin listening for events. If you
  // have some other initialization that must be done asynchronously, then
  // you can defer this call until after that initialization is done.
  xpc_connection_resume(peer);

  dispatch_async(dispatch_get_main_queue(), ^{
    getInitializationInfo(MainConnection);
  });
}

static void fatal_error_handler(void *user_data, const std::string& reason,
                                bool gen_crash_diag) {
  // Write the result out to stderr avoiding errs() because raw_ostreams can
  // call report_fatal_error.
  fprintf(stderr, "SOURCEKITD SERVER FATAL ERROR: %s\n", reason.c_str());
  if (gen_crash_diag)
    ::abort();
}

int main(int argc, const char *argv[]) {
  llvm::install_fatal_error_handler(fatal_error_handler, 0);
  sourcekitd::enableLogging("sourcekit-serv");
  sourcekitd::initialize();

  // Increase the file descriptor limit.
  // FIXME: Portability ?
  static const size_t FDLimit = 4096;
  struct rlimit l;
  if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
    if (l.rlim_cur < FDLimit) {
      l.rlim_cur = FDLimit;
      if (setrlimit(RLIMIT_NOFILE, &l) == 0) {
        LOG_INFO_FUNC(Low, "bumped file descriptor limit to " << FDLimit);
      } else {
        LOG_WARN_FUNC("setrlimit failed: " << llvm::sys::StrError());
      }
    }
  } else {
    LOG_WARN_FUNC("getrlimit failed: " << llvm::sys::StrError());
  }

  xpc_main(sourcekitdServer_event_handler);
  return 0;
}

UIdent SKUIDToUIDMap::get(sourcekitd_uid_t SKDUID) {
  UIdent UID;
  Queue.dispatchSync([&]{
    MapTy::iterator It = Map.find(SKDUID);
    if (It != Map.end())
      UID = It->second;
  });

  return UID;
}

void SKUIDToUIDMap::set(sourcekitd_uid_t SKDUID, UIdent UID) {
  Queue.dispatchBarrier([=]{
    this->Map[SKDUID] = UID;
  });
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "courgette/base_test_unittest.h"
#include "courgette/courgette.h"
#include "courgette/streams.h"

class EnsembleTest : public BaseTest {
 public:

  void TestEnsemble(std::string src_bytes, std::string tgt_bytes) const;

  void PeEnsemble() const;
};

void EnsembleTest::TestEnsemble(std::string src_bytes,
                                std::string tgt_bytes) const {

  courgette::SourceStream source;
  courgette::SourceStream target;

  source.Init(src_bytes);
  target.Init(tgt_bytes);

  courgette::SinkStream patch_sink;

  courgette::Status status;

  status = courgette::GenerateEnsemblePatch(&source, &target, &patch_sink);
  EXPECT_EQ(courgette::C_OK, status);

  courgette::SourceStream patch_source;
  patch_source.Init(patch_sink.Buffer(), patch_sink.Length());

  courgette::SinkStream patch_result;

  status = courgette::ApplyEnsemblePatch(&source, &patch_source, &patch_result);
  EXPECT_EQ(courgette::C_OK, status);

  EXPECT_EQ(target.OriginalLength(), patch_result.Length());
  EXPECT_FALSE(memcmp(target.Buffer(),
                      patch_result.Buffer(),
                      target.OriginalLength()));
}

void EnsembleTest::PeEnsemble() const {
  std::list<std::string> src_ensemble;
  std::list<std::string> tgt_ensemble;

  src_ensemble.push_back("en-US.dll");
  src_ensemble.push_back("setup1.exe");
  src_ensemble.push_back("elf-32-1");
  src_ensemble.push_back("pe-64.exe");

  tgt_ensemble.push_back("en-US.dll");
  tgt_ensemble.push_back("setup2.exe");
  tgt_ensemble.push_back("elf-32-2");
  tgt_ensemble.push_back("pe-64.exe");

  std::string src_bytes = FilesContents(src_ensemble);
  std::string tgt_bytes = FilesContents(tgt_ensemble);

  src_bytes = "aaabbbccc" + src_bytes + "dddeeefff";
  tgt_bytes = "aaagggccc" + tgt_bytes + "dddeeefff";

  TestEnsemble(src_bytes, tgt_bytes);
}

TEST_F(EnsembleTest, All) {
  PeEnsemble();
}
<commit_msg>Disable the Courgette ensemble unittest.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "courgette/base_test_unittest.h"
#include "courgette/courgette.h"
#include "courgette/streams.h"

class EnsembleTest : public BaseTest {
 public:

  void TestEnsemble(std::string src_bytes, std::string tgt_bytes) const;

  void PeEnsemble() const;
};

void EnsembleTest::TestEnsemble(std::string src_bytes,
                                std::string tgt_bytes) const {

  courgette::SourceStream source;
  courgette::SourceStream target;

  source.Init(src_bytes);
  target.Init(tgt_bytes);

  courgette::SinkStream patch_sink;

  courgette::Status status;

  status = courgette::GenerateEnsemblePatch(&source, &target, &patch_sink);
  EXPECT_EQ(courgette::C_OK, status);

  courgette::SourceStream patch_source;
  patch_source.Init(patch_sink.Buffer(), patch_sink.Length());

  courgette::SinkStream patch_result;

  status = courgette::ApplyEnsemblePatch(&source, &patch_source, &patch_result);
  EXPECT_EQ(courgette::C_OK, status);

  EXPECT_EQ(target.OriginalLength(), patch_result.Length());
  EXPECT_FALSE(memcmp(target.Buffer(),
                      patch_result.Buffer(),
                      target.OriginalLength()));
}

void EnsembleTest::PeEnsemble() const {
  std::list<std::string> src_ensemble;
  std::list<std::string> tgt_ensemble;

  src_ensemble.push_back("en-US.dll");
  src_ensemble.push_back("setup1.exe");
  src_ensemble.push_back("elf-32-1");
  src_ensemble.push_back("pe-64.exe");

  tgt_ensemble.push_back("en-US.dll");
  tgt_ensemble.push_back("setup2.exe");
  tgt_ensemble.push_back("elf-32-2");
  tgt_ensemble.push_back("pe-64.exe");

  std::string src_bytes = FilesContents(src_ensemble);
  std::string tgt_bytes = FilesContents(tgt_ensemble);

  src_bytes = "aaabbbccc" + src_bytes + "dddeeefff";
  tgt_bytes = "aaagggccc" + tgt_bytes + "dddeeefff";

  TestEnsemble(src_bytes, tgt_bytes);
}

TEST_F(EnsembleTest, DISABLED_All) {
  // TODO(dgarrett) http://code.google.com/p/chromium/issues/detail?id=101614
  PeEnsemble();
}
<|endoftext|>


<commit_before>//https://code.google.com/p/nya-engine/

#include "fbo.h"
#include "platform_specific_gl.h"

namespace nya_render
{

#ifdef NO_EXTENSIONS_INIT
    #define fbo_glGenFramebuffers glGenFramebuffers
    #define fbo_glBindFramebuffer glBindFramebuffer
	#define fbo_glDeleteFramebuffers glDeleteFramebuffers;
	#define fbo_glFramebufferTexture2D glFramebufferTexture2D;
#else
    PFNGLGENFRAMEBUFFERSPROC fbo_glGenFramebuffers;
	PFNGLBINDFRAMEBUFFERPROC fbo_glBindFramebuffer;
	PFNGLDELETEFRAMEBUFFERSPROC fbo_glDeleteFramebuffers;
	PFNGLFRAMEBUFFERTEXTURE2DPROC fbo_glFramebufferTexture2D;
#endif

bool check_init_fbo()
{
    static bool initialised=false;
    static bool failed=true;
    if(initialised)
        return !failed;

    //if(!has_extension("GL_EXT_framebuffer_object"))
    //    return false;

#ifndef NO_EXTENSIONS_INIT
    fbo_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)get_extension("glGenFramebuffers");
    if(!fbo_glGenFramebuffers)
        return false;

	fbo_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)get_extension("glBindFramebuffer");
    if(!fbo_glBindFramebuffer)
        return false;

	fbo_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)get_extension("glDeleteFramebuffers");
    if(!fbo_glDeleteFramebuffers)
        return false;

	fbo_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)get_extension("glFramebufferTexture2D");
    if(!fbo_glFramebufferTexture2D)
        return false;
#endif

    initialised=true;
    failed=false;

    return true;
}

void fbo::set_color_target(const texture &tex)
{
	if(!check_init_fbo())
		return;

    if(tex.m_gl_type!=GL_TEXTURE_2D)
        return;

    if(m_color_target_idx==tex.m_tex_id)
        return;

    if(!m_fbo_idx)
        fbo_glGenFramebuffers(1,&m_fbo_idx);

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,m_fbo_idx);

    if(!m_color_target_idx && m_depth_target_idx)
    {
        glDrawBuffer(GL_COLOR_ATTACHMENT0);
        glReadBuffer(GL_COLOR_ATTACHMENT0);
    }

    fbo_glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,tex.m_tex_id,0);
    fbo_glBindFramebuffer(GL_FRAMEBUFFER,0);

    m_color_target_idx=tex.m_tex_id;
}

void fbo::set_depth_target(const texture &tex)
{
	if(!check_init_fbo())
		return;

    if(tex.m_gl_type!=GL_TEXTURE_2D)
        return;

    if(m_depth_target_idx==tex.m_tex_id)
        return;

    if(!m_fbo_idx)
        fbo_glGenFramebuffers(1,&m_fbo_idx);

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,m_fbo_idx);

    if(!m_color_target_idx)
    {
        glDrawBuffer(GL_NONE);
        glReadBuffer(GL_NONE);
    }

    fbo_glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,tex.m_tex_id,0);
    fbo_glBindFramebuffer(GL_FRAMEBUFFER,0);

    m_depth_target_idx=tex.m_tex_id;
}

void fbo::release()
{
    if(!m_fbo_idx)
        return;

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,0);
    fbo_glDeleteFramebuffers(1,&m_fbo_idx);

    m_fbo_idx=0;
    m_color_target_idx=0;
    m_depth_target_idx=0;
}

void fbo::bind()
{
	if(!m_fbo_idx)
		return;

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,m_fbo_idx);
}

void fbo::unbind()
{
	if(!m_fbo_idx)
		return;

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,0);
}

}
<commit_msg>fbo fix<commit_after>//https://code.google.com/p/nya-engine/

#include "fbo.h"
#include "platform_specific_gl.h"

namespace nya_render
{

#ifdef NO_EXTENSIONS_INIT
    #define fbo_glGenFramebuffers glGenFramebuffers
    #define fbo_glBindFramebuffer glBindFramebuffer
	#define fbo_glDeleteFramebuffers glDeleteFramebuffers
	#define fbo_glFramebufferTexture2D glFramebufferTexture2D
#else
    PFNGLGENFRAMEBUFFERSPROC fbo_glGenFramebuffers;
	PFNGLBINDFRAMEBUFFERPROC fbo_glBindFramebuffer;
	PFNGLDELETEFRAMEBUFFERSPROC fbo_glDeleteFramebuffers;
	PFNGLFRAMEBUFFERTEXTURE2DPROC fbo_glFramebufferTexture2D;
#endif

bool check_init_fbo()
{
    static bool initialised=false;
    static bool failed=true;
    if(initialised)
        return !failed;

    //if(!has_extension("GL_EXT_framebuffer_object"))
    //    return false;

#ifndef NO_EXTENSIONS_INIT
    fbo_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)get_extension("glGenFramebuffers");
    if(!fbo_glGenFramebuffers)
        return false;

	fbo_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)get_extension("glBindFramebuffer");
    if(!fbo_glBindFramebuffer)
        return false;

	fbo_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)get_extension("glDeleteFramebuffers");
    if(!fbo_glDeleteFramebuffers)
        return false;

	fbo_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)get_extension("glFramebufferTexture2D");
    if(!fbo_glFramebufferTexture2D)
        return false;
#endif

    initialised=true;
    failed=false;

    return true;
}

void fbo::set_color_target(const texture &tex)
{
	if(!check_init_fbo())
		return;

    if(tex.m_gl_type!=GL_TEXTURE_2D)
        return;

    if(m_color_target_idx==tex.m_tex_id)
        return;

    if(!m_fbo_idx)
        fbo_glGenFramebuffers(1,&m_fbo_idx);

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,m_fbo_idx);

    if(!m_color_target_idx && m_depth_target_idx)
    {
        glDrawBuffer(GL_COLOR_ATTACHMENT0);
        glReadBuffer(GL_COLOR_ATTACHMENT0);
    }

    fbo_glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,tex.m_tex_id,0);
    fbo_glBindFramebuffer(GL_FRAMEBUFFER,0);

    m_color_target_idx=tex.m_tex_id;
}

void fbo::set_depth_target(const texture &tex)
{
	if(!check_init_fbo())
		return;

    if(tex.m_gl_type!=GL_TEXTURE_2D)
        return;

    if(m_depth_target_idx==tex.m_tex_id)
        return;

    if(!m_fbo_idx)
        fbo_glGenFramebuffers(1,&m_fbo_idx);

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,m_fbo_idx);

    if(!m_color_target_idx)
    {
        glDrawBuffer(GL_NONE);
        glReadBuffer(GL_NONE);
    }

    fbo_glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,tex.m_tex_id,0);
    fbo_glBindFramebuffer(GL_FRAMEBUFFER,0);

    m_depth_target_idx=tex.m_tex_id;
}

void fbo::release()
{
    if(!m_fbo_idx)
        return;

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,0);
    fbo_glDeleteFramebuffers(1,&m_fbo_idx);

    m_fbo_idx=0;
    m_color_target_idx=0;
    m_depth_target_idx=0;
}

void fbo::bind()
{
	if(!m_fbo_idx)
		return;

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,m_fbo_idx);
}

void fbo::unbind()
{
	if(!m_fbo_idx)
		return;

    fbo_glBindFramebuffer(GL_FRAMEBUFFER,0);
}

}
<|endoftext|>


<commit_before>/* This file is part of Ingen.
 * Copyright (C) 2008-2009 Dave Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <dlfcn.h>
#include <limits.h>
#include <stdlib.h>
#include <glibmm/module.h>
#include <glibmm/miscutils.h>
#include "ingen-config.h"
#include "runtime_paths.hpp"

using namespace std;

namespace Ingen {
namespace Shared {

static std::string bundle_path;

/** Must be called once at startup, and passed a pointer to a function
 * that lives in the 'top level' of the bundle (e.g. the executable).
 * Passing a function defined in a module etc. will not work!
 */
void
set_bundle_path_from_code(void* function)
{
	Dl_info dli;
	dladdr(function, &dli);

#ifdef BUNDLE
	char bin_loc[PATH_MAX];
	realpath(dli.dli_fname, bin_loc);
#else
	const char* bin_loc = dli.dli_fname;
#endif

	string bundle = bin_loc;
	bundle = bundle.substr(0, bundle.find_last_of(G_DIR_SEPARATOR));
	bundle_path = bundle;
}

void
set_bundle_path(const char* path)
{
	bundle_path = path;
}

/** Return the absolute path of a file in an Ingen LV2 bundle
 */
std::string
bundle_file_path(const std::string& name)
{
	return Glib::build_filename(bundle_path, name);
}

/** Return the absolute path of a 'resource' file.
 */
std::string
data_file_path(const std::string& name)
{
#ifdef BUNDLE
	return Glib::build_filename(bundle_path, Glib::build_path(INGEN_DATA_DIR, name));
#else
	return Glib::build_filename(INGEN_DATA_DIR, name);
#endif
}

/** Return the absolute path of a module (dynamically loaded shared library).
 */
std::string
module_path(const std::string& name)
{
	std::string ret;
#ifdef BUNDLE
	ret =  Glib::Module::build_path(Glib::build_path(bundle_path, INGEN_MODULE_DIR), name);
#else
	ret = Glib::Module::build_path(INGEN_MODULE_DIR, name);
#endif
#ifdef __APPLE__
	// MacPorts glib doesnt seem to do portable path building correctly...
	if (ret.substr(ret.length() - 3) == ".so")
		ret = ret.substr(0, ret.length() - 2).append("dylib");
	return ret;
#endif
}

} // namespace Ingen
} // namespace Shared

<commit_msg>Fix module loading on non-Apple (oops).<commit_after>/* This file is part of Ingen.
 * Copyright (C) 2008-2009 Dave Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <dlfcn.h>
#include <limits.h>
#include <stdlib.h>
#include <glibmm/module.h>
#include <glibmm/miscutils.h>
#include "ingen-config.h"
#include "runtime_paths.hpp"

using namespace std;

namespace Ingen {
namespace Shared {

static std::string bundle_path;

/** Must be called once at startup, and passed a pointer to a function
 * that lives in the 'top level' of the bundle (e.g. the executable).
 * Passing a function defined in a module etc. will not work!
 */
void
set_bundle_path_from_code(void* function)
{
	Dl_info dli;
	dladdr(function, &dli);

#ifdef BUNDLE
	char bin_loc[PATH_MAX];
	realpath(dli.dli_fname, bin_loc);
#else
	const char* bin_loc = dli.dli_fname;
#endif

	string bundle = bin_loc;
	bundle = bundle.substr(0, bundle.find_last_of(G_DIR_SEPARATOR));
	bundle_path = bundle;
}

void
set_bundle_path(const char* path)
{
	bundle_path = path;
}

/** Return the absolute path of a file in an Ingen LV2 bundle
 */
std::string
bundle_file_path(const std::string& name)
{
	return Glib::build_filename(bundle_path, name);
}

/** Return the absolute path of a 'resource' file.
 */
std::string
data_file_path(const std::string& name)
{
#ifdef BUNDLE
	return Glib::build_filename(bundle_path, Glib::build_path(INGEN_DATA_DIR, name));
#else
	return Glib::build_filename(INGEN_DATA_DIR, name);
#endif
}

/** Return the absolute path of a module (dynamically loaded shared library).
 */
std::string
module_path(const std::string& name)
{
	std::string ret;
#ifdef BUNDLE
	ret =  Glib::Module::build_path(Glib::build_path(bundle_path, INGEN_MODULE_DIR), name);
#else
	ret = Glib::Module::build_path(INGEN_MODULE_DIR, name);
#endif
#ifdef __APPLE__
	// MacPorts glib doesnt seem to do portable path building correctly...
	if (ret.substr(ret.length() - 3) == ".so")
		ret = ret.substr(0, ret.length() - 2).append("dylib");
#endif
	return ret;
}

} // namespace Ingen
} // namespace Shared

<|endoftext|>


<commit_before>#pragma once

#include <cstdint>
#include <cassert>
#include <vector>
#include <unordered_map>
#include <string>
#include <stdexcept>
#include <functional>

#include "utils/uncopyable.hpp"
#include "utils/tout.hpp"

namespace fr {

struct Config;
struct Camera;
class Image;
class LightList;
struct Shader;
struct Texture;
struct Material;
struct Mesh;
class NetNode;
struct FatRay;

class Library : private Uncopyable {
public:
    explicit Library();
    ~Library();

    // Configs...
    void StoreConfig(Config* config);

    inline Config* LookupConfig() const { return _config; }

    // Cameras...
    void StoreCamera(Camera* camera);

    inline Camera* LookupCamera() const { return _camera; }

    // Images...
    void StoreImage(Image* image);

    inline Image* LookupImage() const { return _image; }

    // Light lists...
    void StoreLightList(LightList* lights);

    inline LightList* LookupLightList() const { return _lights; }

    // Shaders...
    inline uint32_t NextShaderID() const { return _shaders.size(); }

    void StoreShader(uint32_t id, Shader* shader);

    inline Shader* LookupShader(uint32_t id) const {
        assert(id > 0);
        assert(id < _shaders.size());
        return _shaders[id];
    };

    // Textures...
    inline uint32_t NextTextureID() const { return _textures.size(); }

    void StoreTexture(uint32_t id, Texture* texture);

    inline Texture* LookupTexture(uint32_t id) const {
        assert(id > 0);
        assert(id < _textures.size());
        return _textures[id];
    }

    // Materials...
    inline uint32_t NextMaterialID() const { return _materials.size(); }

    void StoreMaterial(uint32_t id, Material* material, const std::string& name);

    inline Material* LookupMaterial(uint32_t id) const {
        assert(id > 0);
        assert(id < _materials.size());
        return _materials[id];
    }

    inline uint32_t LookupMaterial(const std::string& name) const {
        uint32_t id = 0;
        try {
            id = _material_name_index.at(name);
        } catch (std::out_of_range& e) {
            id = 0;
        }
        return id;
    }

    // Meshes...
    inline uint32_t NextMeshID() const { return _meshes.size(); }

    void StoreMesh(uint32_t id, Mesh* mesh);

    inline Mesh* LookupMesh(uint32_t id) const {
        assert(id > 0);
        assert(id < _meshes.size());
        return _meshes[id];
    }

    void ForEachMesh(std::function<void (uint32_t id, Mesh* mesh)> func);

    void ForEachEmissiveMesh(std::function<void (uint32_t id, Mesh* mesh)> func);

    void NaiveIntersect(FatRay* ray, uint32_t me);

    void Intersect(FatRay* ray, uint32_t me);

    // Net nodes...
    void StoreNetNode(uint32_t id, NetNode* node);

    inline NetNode* LookupNetNode(uint32_t id) const {
        assert(id > 0);
        assert(id < _nodes.size());
        return _nodes[id];
    }

    void ForEachNetNode(std::function<void (uint32_t id, NetNode* node)> func);

    template <typename RetType>
    std::vector<RetType> ForEachNetNode(std::function<RetType (uint32_t id, NetNode* node)> func) {
        std::vector<RetType> results(_nodes.size());
        for (uint32_t id = 1; id < _nodes.size(); id++) {
            NetNode* node = _nodes[id];
            if (node == nullptr) continue;
            RetType result = func(id, node);
            results.insert(results.begin() + id, result);
        }
        return results;
    }

    // Spatial index access for net nodes...
    void BuildSpatialIndex();

    inline uint32_t LookupNetNodeBySpaceCode(uint64_t spacecode) const {
#ifndef NDEBUG
        if (_chunk_size == 0) {
            TERRLN("Attempted to lookup net node by space code without first building the spatial index!");
            exit(EXIT_FAILURE);
        }
#endif
        return _spatial_index.at(spacecode / _chunk_size);
    }

private:
    Config *_config;
    Camera* _camera;
    Image* _image;
    LightList* _lights;
    std::vector<Shader*> _shaders;
    std::vector<Texture*> _textures;
    std::vector<Material*> _materials;
    std::vector<Mesh*> _meshes;
    std::vector<NetNode*> _nodes;
    std::unordered_map<std::string, uint32_t> _material_name_index;
    std::vector<uint32_t> _spatial_index;
    std::vector<uint32_t> _emissive_index;
    uint64_t _chunk_size;
};

} // namespace fr
<commit_msg>Don't need NaiveIntersect anymore.<commit_after>#pragma once

#include <cstdint>
#include <cassert>
#include <vector>
#include <unordered_map>
#include <string>
#include <stdexcept>
#include <functional>

#include "utils/uncopyable.hpp"
#include "utils/tout.hpp"

namespace fr {

struct Config;
struct Camera;
class Image;
class LightList;
struct Shader;
struct Texture;
struct Material;
struct Mesh;
class NetNode;
struct FatRay;

class Library : private Uncopyable {
public:
    explicit Library();
    ~Library();

    // Configs...
    void StoreConfig(Config* config);

    inline Config* LookupConfig() const { return _config; }

    // Cameras...
    void StoreCamera(Camera* camera);

    inline Camera* LookupCamera() const { return _camera; }

    // Images...
    void StoreImage(Image* image);

    inline Image* LookupImage() const { return _image; }

    // Light lists...
    void StoreLightList(LightList* lights);

    inline LightList* LookupLightList() const { return _lights; }

    // Shaders...
    inline uint32_t NextShaderID() const { return _shaders.size(); }

    void StoreShader(uint32_t id, Shader* shader);

    inline Shader* LookupShader(uint32_t id) const {
        assert(id > 0);
        assert(id < _shaders.size());
        return _shaders[id];
    };

    // Textures...
    inline uint32_t NextTextureID() const { return _textures.size(); }

    void StoreTexture(uint32_t id, Texture* texture);

    inline Texture* LookupTexture(uint32_t id) const {
        assert(id > 0);
        assert(id < _textures.size());
        return _textures[id];
    }

    // Materials...
    inline uint32_t NextMaterialID() const { return _materials.size(); }

    void StoreMaterial(uint32_t id, Material* material, const std::string& name);

    inline Material* LookupMaterial(uint32_t id) const {
        assert(id > 0);
        assert(id < _materials.size());
        return _materials[id];
    }

    inline uint32_t LookupMaterial(const std::string& name) const {
        uint32_t id = 0;
        try {
            id = _material_name_index.at(name);
        } catch (std::out_of_range& e) {
            id = 0;
        }
        return id;
    }

    // Meshes...
    inline uint32_t NextMeshID() const { return _meshes.size(); }

    void StoreMesh(uint32_t id, Mesh* mesh);

    inline Mesh* LookupMesh(uint32_t id) const {
        assert(id > 0);
        assert(id < _meshes.size());
        return _meshes[id];
    }

    void ForEachMesh(std::function<void (uint32_t id, Mesh* mesh)> func);

    void ForEachEmissiveMesh(std::function<void (uint32_t id, Mesh* mesh)> func);

    void Intersect(FatRay* ray, uint32_t me);

    // Net nodes...
    void StoreNetNode(uint32_t id, NetNode* node);

    inline NetNode* LookupNetNode(uint32_t id) const {
        assert(id > 0);
        assert(id < _nodes.size());
        return _nodes[id];
    }

    void ForEachNetNode(std::function<void (uint32_t id, NetNode* node)> func);

    template <typename RetType>
    std::vector<RetType> ForEachNetNode(std::function<RetType (uint32_t id, NetNode* node)> func) {
        std::vector<RetType> results(_nodes.size());
        for (uint32_t id = 1; id < _nodes.size(); id++) {
            NetNode* node = _nodes[id];
            if (node == nullptr) continue;
            RetType result = func(id, node);
            results.insert(results.begin() + id, result);
        }
        return results;
    }

    // Spatial index access for net nodes...
    void BuildSpatialIndex();

    inline uint32_t LookupNetNodeBySpaceCode(uint64_t spacecode) const {
#ifndef NDEBUG
        if (_chunk_size == 0) {
            TERRLN("Attempted to lookup net node by space code without first building the spatial index!");
            exit(EXIT_FAILURE);
        }
#endif
        return _spatial_index.at(spacecode / _chunk_size);
    }

private:
    Config *_config;
    Camera* _camera;
    Image* _image;
    LightList* _lights;
    std::vector<Shader*> _shaders;
    std::vector<Texture*> _textures;
    std::vector<Material*> _materials;
    std::vector<Mesh*> _meshes;
    std::vector<NetNode*> _nodes;
    std::unordered_map<std::string, uint32_t> _material_name_index;
    std::vector<uint32_t> _spatial_index;
    std::vector<uint32_t> _emissive_index;
    uint64_t _chunk_size;
};

} // namespace fr
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: XMLChangeInfoContext.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: dvo $ $Date: 2001-01-24 16:49:51 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLCHANGEINFOCONTEXT_HXX
#define _XMLOFF_XMLCHANGEINFOCONTEXT_HXX

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace xml { namespace sax { class XAttributeList; } }
} } }
class XMLChangedRegionImportContext;

/**
 * Import <office:change-info> elements as children of <text:changed-region>
 * elements. The attribute values will be passed to the enclosing
 * XMLChangedRegionImportContext (which has to be passed down in the
 * constructor).
 */
class XMLChangeInfoContext : public SvXMLImportContext
{
    const ::rtl::OUString& rType;

    ::rtl::OUString sAuthor;
    ::rtl::OUString sDateTime;
    ::rtl::OUStringBuffer sCommentBuffer;

    XMLChangedRegionImportContext& rChangedRegion;

public:

    TYPEINFO();

    XMLChangeInfoContext(
        SvXMLImport& rImport,
        sal_uInt16 nPrefix,
        const ::rtl::OUString& rLocalName,
        XMLChangedRegionImportContext& rChangedRegion,
        const ::rtl::OUString& rChangeType);

    ~XMLChangeInfoContext();

    virtual void StartElement(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList> & xAttrList);

    virtual SvXMLImportContext *CreateChildContext(
        USHORT nPrefix,
        const ::rtl::OUString& rLocalName,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList >& xAttrList );

    virtual void EndElement();

};

#endif
<commit_msg>INTEGRATION: CWS oasis (1.2.288); FILE MERGED 2004/05/12 11:00:37 mib 1.2.288.1: - #i20153#: changed <office:annotation> and <office:change-info><commit_after>/*************************************************************************
 *
 *  $RCSfile: XMLChangeInfoContext.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-13 08:31:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLCHANGEINFOCONTEXT_HXX
#define _XMLOFF_XMLCHANGEINFOCONTEXT_HXX

#ifndef _XMLOFF_XMLICTXT_HXX
#include "xmlictxt.hxx"
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace xml { namespace sax { class XAttributeList; } }
} } }
class XMLChangedRegionImportContext;

/**
 * Import <office:change-info> elements as children of <text:changed-region>
 * elements. The attribute values will be passed to the enclosing
 * XMLChangedRegionImportContext (which has to be passed down in the
 * constructor).
 */
class XMLChangeInfoContext : public SvXMLImportContext
{
    const ::rtl::OUString& rType;

    ::rtl::OUStringBuffer sAuthorBuffer;
    ::rtl::OUStringBuffer sDateTimeBuffer;
    ::rtl::OUStringBuffer sCommentBuffer;

    XMLChangedRegionImportContext& rChangedRegion;

public:

    TYPEINFO();

    XMLChangeInfoContext(
        SvXMLImport& rImport,
        sal_uInt16 nPrefix,
        const ::rtl::OUString& rLocalName,
        XMLChangedRegionImportContext& rChangedRegion,
        const ::rtl::OUString& rChangeType);

    ~XMLChangeInfoContext();

    virtual void StartElement(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList> & xAttrList);

    virtual SvXMLImportContext *CreateChildContext(
        USHORT nPrefix,
        const ::rtl::OUString& rLocalName,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList >& xAttrList );

    virtual void EndElement();

};

#endif
<|endoftext|>


<commit_before><commit_msg>Protect X11 with ifdef USE_X11 in global commands test<commit_after><|endoftext|>