Bypass boost::numeric_cast checks for coordinate values that have already been validated (#4059)

(i.e. stuff that's stored in our datafiles).  Keep those checks for user-supplied values
(i.e. coordinates coming from files during preprocessing, or coordinates supplied by users
 during requests)
This commit is contained in:
Daniel Patterson
2017-05-19 10:52:44 -07:00
committed by GitHub
parent 4964d0dcbd
commit 570d81c6dd
4 changed files with 71 additions and 20 deletions
+50 -2
View File
@@ -53,16 +53,29 @@ struct latitude
struct longitude
{
};
struct unsafelatitude
{
};
struct unsafelongitude
{
};
}
// Internal lon/lat types - assumed to be range safe
using FixedLatitude = Alias<std::int32_t, tag::latitude>;
using FixedLongitude = Alias<std::int32_t, tag::longitude>;
using FloatLatitude = Alias<double, tag::latitude>;
using FloatLongitude = Alias<double, tag::longitude>;
// Types used for external input data - conversion functions perform extra
// range checks on these (toFixed/toFloat, etc)
using UnsafeFloatLatitude = Alias<double, tag::unsafelatitude>;
using UnsafeFloatLongitude = Alias<double, tag::unsafelongitude>;
static_assert(std::is_pod<FixedLatitude>(), "FixedLatitude is not a valid alias");
static_assert(std::is_pod<FixedLongitude>(), "FixedLongitude is not a valid alias");
static_assert(std::is_pod<FloatLatitude>(), "FloatLatitude is not a valid alias");
static_assert(std::is_pod<FloatLongitude>(), "FloatLongitude is not a valid alias");
static_assert(std::is_pod<UnsafeFloatLatitude>(), "UnsafeFloatLatitude is not a valid alias");
static_assert(std::is_pod<UnsafeFloatLongitude>(), "UnsafeFloatLongitude is not a valid alias");
/**
* Converts a typed latitude from floating to fixed representation.
@@ -72,6 +85,21 @@ static_assert(std::is_pod<FloatLongitude>(), "FloatLongitude is not a valid alia
* \see Coordinate, toFloating
*/
inline FixedLatitude toFixed(const FloatLatitude floating)
{
const auto latitude = static_cast<double>(floating);
const auto fixed = static_cast<std::int32_t>(std::round(latitude * COORDINATE_PRECISION));
return FixedLatitude{fixed};
}
/**
* Converts a typed latitude from floating to fixed representation. Also performs an overflow check
* to ensure that the value fits inside the fixed representation.
*
* \param floating typed latitude in floating representation.
* \return typed latitude in fixed representation
* \see Coordinate, toFloating
*/
inline FixedLatitude toFixed(const UnsafeFloatLatitude floating)
{
const auto latitude = static_cast<double>(floating);
const auto fixed =
@@ -87,6 +115,21 @@ inline FixedLatitude toFixed(const FloatLatitude floating)
* \see Coordinate, toFloating
*/
inline FixedLongitude toFixed(const FloatLongitude floating)
{
const auto longitude = static_cast<double>(floating);
const auto fixed = static_cast<std::int32_t>(std::round(longitude * COORDINATE_PRECISION));
return FixedLongitude{fixed};
}
/**
* Converts a typed longitude from floating to fixed representation. Also performns an overflow
* check to ensure that the value fits inside the fixed representation.
*
* \param floating typed longitude in floating representation.
* \return typed latitude in fixed representation
* \see Coordinate, toFloating
*/
inline FixedLongitude toFixed(const UnsafeFloatLongitude floating)
{
const auto longitude = static_cast<double>(floating);
const auto fixed =
@@ -104,7 +147,7 @@ inline FixedLongitude toFixed(const FloatLongitude floating)
inline FloatLatitude toFloating(const FixedLatitude fixed)
{
const auto latitude = static_cast<std::int32_t>(fixed);
const auto floating = boost::numeric_cast<double>(latitude / COORDINATE_PRECISION);
const auto floating = static_cast<double>(latitude) / COORDINATE_PRECISION;
return FloatLatitude{floating};
}
@@ -118,7 +161,7 @@ inline FloatLatitude toFloating(const FixedLatitude fixed)
inline FloatLongitude toFloating(const FixedLongitude fixed)
{
const auto longitude = static_cast<std::int32_t>(fixed);
const auto floating = boost::numeric_cast<double>(longitude / COORDINATE_PRECISION);
const auto floating = static_cast<double>(longitude) / COORDINATE_PRECISION;
return FloatLongitude{floating};
}
@@ -152,6 +195,11 @@ struct Coordinate
{
}
Coordinate(const UnsafeFloatLongitude lon_, const UnsafeFloatLatitude lat_)
: Coordinate(toFixed(lon_), toFixed(lat_))
{
}
Coordinate(const FixedLongitude lon_, const FixedLatitude lat_) : lon(lon_), lat(lat_) {}
template <class T> Coordinate(const T &coordinate) : lon(coordinate.lon), lat(coordinate.lat)