DOS -> UNIX file format

This commit is contained in:
Patrick Niklaus 2016-01-02 14:44:47 +01:00
parent 078f71c144
commit d936009ea1

View File

@ -1,256 +1,256 @@
/* /*
Copyright (c) 2015, Project OSRM contributors Copyright (c) 2015, Project OSRM contributors
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer. of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution. other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "restriction_parser.hpp" #include "restriction_parser.hpp"
#include "extraction_way.hpp" #include "extraction_way.hpp"
#include "../data_structures/external_memory_node.hpp" #include "../data_structures/external_memory_node.hpp"
#include "../util/lua_util.hpp" #include "../util/lua_util.hpp"
#include "../util/osrm_exception.hpp" #include "../util/osrm_exception.hpp"
#include "../util/simple_logger.hpp" #include "../util/simple_logger.hpp"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp> #include <boost/algorithm/string/regex.hpp>
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <boost/optional/optional.hpp> #include <boost/optional/optional.hpp>
#include <osmium/osm.hpp> #include <osmium/osm.hpp>
#include <osmium/tags/regex_filter.hpp> #include <osmium/tags/regex_filter.hpp>
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
namespace namespace
{ {
int lua_error_callback(lua_State *lua_state) int lua_error_callback(lua_State *lua_state)
{ {
std::string error_msg = lua_tostring(lua_state, -1); std::string error_msg = lua_tostring(lua_state, -1);
throw osrm::exception("ERROR occurred in profile script:\n" + error_msg); throw osrm::exception("ERROR occurred in profile script:\n" + error_msg);
} }
} }
RestrictionParser::RestrictionParser(lua_State *lua_state) : use_turn_restrictions(true) RestrictionParser::RestrictionParser(lua_State *lua_state) : use_turn_restrictions(true)
{ {
ReadUseRestrictionsSetting(lua_state); ReadUseRestrictionsSetting(lua_state);
if (use_turn_restrictions) if (use_turn_restrictions)
{ {
ReadRestrictionExceptions(lua_state); ReadRestrictionExceptions(lua_state);
} }
} }
void RestrictionParser::ReadUseRestrictionsSetting(lua_State *lua_state) void RestrictionParser::ReadUseRestrictionsSetting(lua_State *lua_state)
{ {
if (0 == luaL_dostring(lua_state, "return use_turn_restrictions\n") && if (0 == luaL_dostring(lua_state, "return use_turn_restrictions\n") &&
lua_isboolean(lua_state, -1)) lua_isboolean(lua_state, -1))
{ {
use_turn_restrictions = lua_toboolean(lua_state, -1); use_turn_restrictions = lua_toboolean(lua_state, -1);
} }
if (use_turn_restrictions) if (use_turn_restrictions)
{ {
SimpleLogger().Write() << "Using turn restrictions"; SimpleLogger().Write() << "Using turn restrictions";
} }
else else
{ {
SimpleLogger().Write() << "Ignoring turn restrictions"; SimpleLogger().Write() << "Ignoring turn restrictions";
} }
} }
void RestrictionParser::ReadRestrictionExceptions(lua_State *lua_state) void RestrictionParser::ReadRestrictionExceptions(lua_State *lua_state)
{ {
if (lua_function_exists(lua_state, "get_exceptions")) if (lua_function_exists(lua_state, "get_exceptions"))
{ {
luabind::set_pcall_callback(&lua_error_callback); luabind::set_pcall_callback(&lua_error_callback);
// get list of turn restriction exceptions // get list of turn restriction exceptions
luabind::call_function<void>(lua_state, "get_exceptions", luabind::call_function<void>(lua_state, "get_exceptions",
boost::ref(restriction_exceptions)); boost::ref(restriction_exceptions));
const unsigned exception_count = restriction_exceptions.size(); const unsigned exception_count = restriction_exceptions.size();
SimpleLogger().Write() << "Found " << exception_count SimpleLogger().Write() << "Found " << exception_count
<< " exceptions to turn restrictions:"; << " exceptions to turn restrictions:";
for (const std::string &str : restriction_exceptions) for (const std::string &str : restriction_exceptions)
{ {
SimpleLogger().Write() << " " << str; SimpleLogger().Write() << " " << str;
} }
} }
else else
{ {
SimpleLogger().Write() << "Found no exceptions to turn restrictions"; SimpleLogger().Write() << "Found no exceptions to turn restrictions";
} }
} }
/** /**
* Tries to parse an relation as turn restriction. This can fail for a number of * Tries to parse an relation as turn restriction. This can fail for a number of
* reasons, this the return type is a boost::optional<T>. * reasons, this the return type is a boost::optional<T>.
* *
* Some restrictions can also be ignored: See the ```get_exceptions``` function * Some restrictions can also be ignored: See the ```get_exceptions``` function
* in the corresponding profile. * in the corresponding profile.
*/ */
boost::optional<InputRestrictionContainer> boost::optional<InputRestrictionContainer>
RestrictionParser::TryParse(const osmium::Relation &relation) const RestrictionParser::TryParse(const osmium::Relation &relation) const
{ {
// return if turn restrictions should be ignored // return if turn restrictions should be ignored
if (!use_turn_restrictions) if (!use_turn_restrictions)
{ {
return {}; return {};
} }
osmium::tags::KeyPrefixFilter filter(false); osmium::tags::KeyPrefixFilter filter(false);
filter.add(true, "restriction"); filter.add(true, "restriction");
const osmium::TagList &tag_list = relation.tags(); const osmium::TagList &tag_list = relation.tags();
osmium::tags::KeyPrefixFilter::iterator fi_begin(filter, tag_list.begin(), tag_list.end()); osmium::tags::KeyPrefixFilter::iterator fi_begin(filter, tag_list.begin(), tag_list.end());
osmium::tags::KeyPrefixFilter::iterator fi_end(filter, tag_list.end(), tag_list.end()); osmium::tags::KeyPrefixFilter::iterator fi_end(filter, tag_list.end(), tag_list.end());
// if it's a restriction, continue; // if it's a restriction, continue;
if (std::distance(fi_begin, fi_end) == 0) if (std::distance(fi_begin, fi_end) == 0)
{ {
return {}; return {};
} }
// check if the restriction should be ignored // check if the restriction should be ignored
const char *except = relation.get_value_by_key("except"); const char *except = relation.get_value_by_key("except");
if (except != nullptr && ShouldIgnoreRestriction(except)) if (except != nullptr && ShouldIgnoreRestriction(except))
{ {
return {}; return {};
} }
bool is_only_restriction = false; bool is_only_restriction = false;
for (; fi_begin != fi_end; ++fi_begin) for (; fi_begin != fi_end; ++fi_begin)
{ {
const std::string key(fi_begin->key()); const std::string key(fi_begin->key());
const std::string value(fi_begin->value()); const std::string value(fi_begin->value());
if (value.find("only_") == 0) if (value.find("only_") == 0)
{ {
is_only_restriction = true; is_only_restriction = true;
} }
// if the "restriction*" key is longer than 11 chars, it is a conditional exception (i.e. // if the "restriction*" key is longer than 11 chars, it is a conditional exception (i.e.
// "restriction:<transportation_type>") // "restriction:<transportation_type>")
if (key.size() > 11) if (key.size() > 11)
{ {
const auto ex_suffix = [&](const std::string &exception) const auto ex_suffix = [&](const std::string &exception)
{ {
return boost::algorithm::ends_with(key, exception); return boost::algorithm::ends_with(key, exception);
}; };
bool is_actually_restricted = bool is_actually_restricted =
std::any_of(begin(restriction_exceptions), end(restriction_exceptions), ex_suffix); std::any_of(begin(restriction_exceptions), end(restriction_exceptions), ex_suffix);
if (!is_actually_restricted) if (!is_actually_restricted)
{ {
return {}; return {};
} }
} }
} }
InputRestrictionContainer restriction_container(is_only_restriction); InputRestrictionContainer restriction_container(is_only_restriction);
for (const auto &member : relation.members()) for (const auto &member : relation.members())
{ {
const char *role = member.role(); const char *role = member.role();
if (strcmp("from", role) != 0 && strcmp("to", role) != 0 && strcmp("via", role) != 0) if (strcmp("from", role) != 0 && strcmp("to", role) != 0 && strcmp("via", role) != 0)
{ {
continue; continue;
} }
switch (member.type()) switch (member.type())
{ {
case osmium::item_type::node: case osmium::item_type::node:
// Make sure nodes appear only in the role if a via node // Make sure nodes appear only in the role if a via node
if (0 == strcmp("from", role) || 0 == strcmp("to", role)) if (0 == strcmp("from", role) || 0 == strcmp("to", role))
{ {
continue; continue;
} }
BOOST_ASSERT(0 == strcmp("via", role)); BOOST_ASSERT(0 == strcmp("via", role));
// set via node id // set via node id
restriction_container.restriction.via.node = member.ref(); restriction_container.restriction.via.node = member.ref();
break; break;
case osmium::item_type::way: case osmium::item_type::way:
BOOST_ASSERT(0 == strcmp("from", role) || 0 == strcmp("to", role) || BOOST_ASSERT(0 == strcmp("from", role) || 0 == strcmp("to", role) ||
0 == strcmp("via", role)); 0 == strcmp("via", role));
if (0 == strcmp("from", role)) if (0 == strcmp("from", role))
{ {
restriction_container.restriction.from.way = member.ref(); restriction_container.restriction.from.way = member.ref();
} }
else if (0 == strcmp("to", role)) else if (0 == strcmp("to", role))
{ {
restriction_container.restriction.to.way = member.ref(); restriction_container.restriction.to.way = member.ref();
} }
// else if (0 == strcmp("via", role)) // else if (0 == strcmp("via", role))
// { // {
// not yet suppported // not yet suppported
// restriction_container.restriction.via.way = member.ref(); // restriction_container.restriction.via.way = member.ref();
// } // }
break; break;
case osmium::item_type::relation: case osmium::item_type::relation:
// not yet supported, but who knows what the future holds... // not yet supported, but who knows what the future holds...
break; break;
default: default:
// shouldn't ever happen // shouldn't ever happen
break; break;
} }
} }
return boost::make_optional(std::move(restriction_container)); return boost::make_optional(std::move(restriction_container));
} }
bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const
{ {
// should this restriction be ignored? yes if there's an overlap between: // should this restriction be ignored? yes if there's an overlap between:
// a) the list of modes in the except tag of the restriction // a) the list of modes in the except tag of the restriction
// (except_tag_string), eg: except=bus;bicycle // (except_tag_string), eg: except=bus;bicycle
// b) the lua profile defines a hierachy of modes, // b) the lua profile defines a hierachy of modes,
// eg: [access, vehicle, bicycle] // eg: [access, vehicle, bicycle]
if (except_tag_string.empty()) if (except_tag_string.empty())
{ {
return false; return false;
} }
// Be warned, this is quadratic work here, but we assume that // Be warned, this is quadratic work here, but we assume that
// only a few exceptions are actually defined. // only a few exceptions are actually defined.
std::vector<std::string> exceptions; std::vector<std::string> exceptions;
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*")); boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
return std::any_of(std::begin(exceptions), std::end(exceptions), return std::any_of(std::begin(exceptions), std::end(exceptions),
[&](const std::string &current_string) [&](const std::string &current_string)
{ {
if (std::end(restriction_exceptions) != if (std::end(restriction_exceptions) !=
std::find(std::begin(restriction_exceptions), std::find(std::begin(restriction_exceptions),
std::end(restriction_exceptions), current_string)) std::end(restriction_exceptions), current_string))
{ {
return true; return true;
} }
return false; return false;
}); });
} }