<commit_before>#pragma once

#include <cmath>
#include <string>

#include "base/macros.hpp"

namespace principia {
namespace quantities {

template<int64_t LengthExponent, int64_t MassExponent, int64_t TimeExponent,
         int64_t CurrentExponent, int64_t TemperatureExponent,
         int64_t AmountExponent, int64_t LuminousIntensityExponent,
         int64_t WindingExponent, int64_t AngleExponent,
         int64_t SolidAngleExponent>
struct Dimensions {
  enum {
    Length            = LengthExponent,
    Mass              = MassExponent,
    Time              = TimeExponent,
    Current           = CurrentExponent,
    Temperature       = TemperatureExponent,
    Amount            = AmountExponent,
    LuminousIntensity = LuminousIntensityExponent,
    Winding           = WindingExponent,
    Angle             = AngleExponent,
    SolidAngle        = SolidAngleExponent
  };

  static int const kMinExponent = -16;
  static int const kMaxExponent = 15;
  static int const kExponentBits = 5;
  static int const kExponentMask = 0x1F;

  static_assert(LengthExponent >= kMinExponent &&
                LengthExponent <= kMaxExponent,
                "Invalid length exponent");
  static_assert(MassExponent >= kMinExponent &&
                MassExponent <= kMaxExponent,
                "Invalid mass exponent");
  static_assert(TimeExponent >= kMinExponent &&
                TimeExponent <= kMaxExponent,
                "Invalid time exponent");
  static_assert(CurrentExponent >= kMinExponent &&
                CurrentExponent <= kMaxExponent,
                "Invalid current exponent");
  static_assert(TemperatureExponent >= kMinExponent &&
                TemperatureExponent <= kMaxExponent,
                "Invalid temperature exponent");
  static_assert(AmountExponent >= kMinExponent &&
                AmountExponent <= kMaxExponent,
                "Invalid amount exponent");
  static_assert(LuminousIntensityExponent >= kMinExponent &&
                LuminousIntensityExponent <= kMaxExponent,
                "Invalid luminous intensity exponent");
  static_assert(AngleExponent >= kMinExponent &&
                AngleExponent <= kMaxExponent,
                "Invalid angle exponent");
  static_assert(SolidAngleExponent >= kMinExponent &&
                SolidAngleExponent <= kMaxExponent,
                "Invalid solid angle exponent");
  static_assert(WindingExponent >= kMinExponent &&
                WindingExponent <= kMaxExponent,
                "Invalid winding exponent");

  // The NOLINT are because glint is confused by the binary and.  I kid you not.
  static int64_t const representation =
      (LengthExponent & kExponentMask)                                 |  // NOLINT
      (MassExponent & kExponentMask)              << 1 * kExponentBits |  // NOLINT
      (TimeExponent & kExponentMask)              << 2 * kExponentBits |  // NOLINT
      (CurrentExponent & kExponentMask)           << 3 * kExponentBits |  // NOLINT
      (TemperatureExponent & kExponentMask)       << 4 * kExponentBits |  // NOLINT
      (AmountExponent & kExponentMask)            << 5 * kExponentBits |  // NOLINT
      (LuminousIntensityExponent & kExponentMask) << 6 * kExponentBits |  // NOLINT
      (AngleExponent & kExponentMask)             << 7 * kExponentBits |  // NOLINT
      (SolidAngleExponent & kExponentMask)        << 8 * kExponentBits |  // NOLINT
      (WindingExponent & kExponentMask)           << 9 * kExponentBits;   // NOLINT
};

namespace internal {
template<typename Q>
struct Collapse { using Type = Q; };
template<>
struct Collapse<Quantity<NoDimensions>> { using Type = double; };
template<typename Left, typename Right>
struct ProductGenerator {
  enum {
    Length            = Left::Dimensions::Length + Right::Dimensions::Length,
    Mass              = Left::Dimensions::Mass + Right::Dimensions::Mass,
    Time              = Left::Dimensions::Time + Right::Dimensions::Time,
    Current           = Left::Dimensions::Current + Right::Dimensions::Current,
    Temperature       = Left::Dimensions::Temperature +
                        Right::Dimensions::Temperature,
    Amount            = Left::Dimensions::Amount + Right::Dimensions::Amount,
    LuminousIntensity = Left::Dimensions::LuminousIntensity +
                        Right:: Dimensions::LuminousIntensity,
    Winding           = Left::Dimensions::Winding + Right::Dimensions::Winding,
    Angle             = Left::Dimensions::Angle + Right::Dimensions::Angle,
    SolidAngle        = Left::Dimensions::SolidAngle +
                        Right::Dimensions::SolidAngle
  };
  using Type = typename Collapse<
      Quantity<Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                          LuminousIntensity, Winding, Angle,
                          SolidAngle>>>::Type;
};
template<typename Left>
struct ProductGenerator<Left, double> { using Type = Left; };
template<typename Right>
struct ProductGenerator<double, Right> { using Type = Right; };
template<>
struct ProductGenerator<double, double> {
  using Type = double;
};
template<typename Left, typename Right>
struct QuotientGenerator {
  enum {
    Length            = Left::Dimensions::Length - Right::Dimensions::Length,
    Mass              = Left::Dimensions::Mass - Right::Dimensions::Mass,
    Time              = Left::Dimensions::Time - Right::Dimensions::Time,
    Current           = Left::Dimensions::Current - Right::Dimensions::Current,
    Temperature       = Left::Dimensions::Temperature -
                        Right::Dimensions::Temperature,
    Amount            = Left::Dimensions::Amount - Right::Dimensions::Amount,
    LuminousIntensity = Left::Dimensions::LuminousIntensity -
                        Right:: Dimensions::LuminousIntensity,
    Winding           = Left::Dimensions::Winding - Right::Dimensions::Winding,
    Angle             = Left::Dimensions::Angle - Right::Dimensions::Angle,
    SolidAngle        = Left::Dimensions::SolidAngle -
                        Right::Dimensions::SolidAngle
  };
  using Type = typename Collapse<
      Quantity<Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                          LuminousIntensity, Winding, Angle,
                          SolidAngle>>>::Type;
};
template<typename Left>
struct QuotientGenerator<Left, double> { using Type = Left; };
template<>
struct QuotientGenerator<double, double> {
  using Type = double;
};
template<typename Right>
struct QuotientGenerator<double, Right> {
  enum {
    Length            = -Right::Dimensions::Length,
    Mass              = -Right::Dimensions::Mass,
    Time              = -Right::Dimensions::Time,
    Current           = -Right::Dimensions::Current,
    Temperature       = -Right::Dimensions::Temperature,
    Amount            = -Right::Dimensions::Amount,
    LuminousIntensity = -Right::Dimensions::LuminousIntensity,
    Winding           = -Right::Dimensions::Winding,
    Angle             = -Right::Dimensions::Angle,
    SolidAngle        = -Right::Dimensions::SolidAngle
  };
  using Type = Quantity<
      Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                 LuminousIntensity, Winding, Angle, SolidAngle>>;
};

template<typename T, int exponent>
struct ExponentiationGenerator<T, exponent, std::enable_if_t<(exponent > 1)>> {
  using Type = Product<typename ExponentiationGenerator<T, exponent - 1>::Type,
                       T>;
};

template<typename T, int exponent>
struct ExponentiationGenerator<T, exponent, std::enable_if_t<(exponent < 1)>>{
  using Type = Quotient<typename ExponentiationGenerator<T, exponent + 1>::Type,
                        T>;
};

template<typename T, int exponent>
struct ExponentiationGenerator<T, exponent, std::enable_if_t<(exponent == 1)>>{
  using Type = T;
};

}  // namespace internal

template<typename D>
inline Quantity<D>::Quantity() : magnitude_(0) {}

template<typename D>
inline Quantity<D>::Quantity(double const magnitude) : magnitude_(magnitude) {}

template<typename D>
inline Quantity<D>& Quantity<D>::operator+=(Quantity const& right) {
  magnitude_ += right.magnitude_;
  return *this;
}

template<typename D>
inline Quantity<D>& Quantity<D>::operator-=(Quantity const& right) {
  magnitude_ -= right.magnitude_;
  return *this;
}

template<typename D>
inline Quantity<D>& Quantity<D>::operator*=(double const right) {
  magnitude_ *= right;
  return *this;
}

template<typename D>
inline Quantity<D>& Quantity<D>::operator/=(double const right) {
  magnitude_ /= right;
  return *this;
}

// Additive group

template<typename D>
inline Quantity<D> Quantity<D>::operator+() const {
  return *this;
}

template<typename D>
inline Quantity<D> Quantity<D>::operator-() const {
  return Quantity(-magnitude_);
}

template<typename D>
inline Quantity<D> Quantity<D>::operator+(Quantity const& right) const {
  return Quantity(magnitude_ + right.magnitude_);
}

template<typename D>
inline Quantity<D> Quantity<D>::operator-(Quantity const& right) const {
  return Quantity(magnitude_ - right.magnitude_);
}

// Comparison operators

template<typename D>
inline bool Quantity<D>::operator>(Quantity const& right) const {
  return magnitude_ > right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator<(Quantity const& right) const {
  return magnitude_ < right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator>=(Quantity const& right) const {
  return magnitude_ >= right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator<=(Quantity const& right) const {
  return magnitude_ <= right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator==(Quantity const& right) const {
  return magnitude_ == right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator!=(Quantity const& right) const {
  return magnitude_ != right.magnitude_;
}

template<typename D>
void Quantity<D>::WriteToMessage(
    not_null<serialization::Quantity*> const message) const {
  message->set_dimensions(D::representation);
  message->set_magnitude(magnitude_);
}

template<typename D>
Quantity<D> Quantity<D>::ReadFromMessage(
    serialization::Quantity const& message) {
  CHECK_EQ(D::representation, message.dimensions());
  return Quantity(message.magnitude());
}

// Multiplicative group

template<typename D>
inline Quantity<D> Quantity<D>::operator/(double const right) const {
  return Quantity(magnitude_ / right);
}

template<typename D>
inline Quantity<D> Quantity<D>::operator*(double const right) const {
  return Quantity(magnitude_ * right);
}

template<typename LDimensions, typename RDimensions>
inline internal::Product<Quantity<LDimensions>, Quantity<RDimensions>>
operator*(Quantity<LDimensions> const& left,
          Quantity<RDimensions> const& right) {
  return Product<Quantity<LDimensions>,
                 Quantity<RDimensions>>(left.magnitude_ * right.magnitude_);
}

template<typename LDimensions, typename RDimensions>
inline internal::Quotient<Quantity<LDimensions>, Quantity<RDimensions>>
operator/(Quantity<LDimensions> const& left,
          Quantity<RDimensions> const& right) {
  return Quotient<Quantity<LDimensions>,
                  Quantity<RDimensions>>(left.magnitude_ / right.magnitude_);
}

template<typename RDimensions>
FORCE_INLINE Quantity<RDimensions> operator*(double const left,
                                       Quantity<RDimensions> const& right) {
  return Quantity<RDimensions>(left * right.magnitude_);
}

template<typename RDimensions>
inline typename Quantity<RDimensions>::Inverse operator/(
    double const left,
    Quantity<RDimensions> const& right) {
  return typename Quantity<RDimensions>::Inverse(left / right.magnitude_);
}

template<int exponent>
inline double Pow(double x) {
  return std::pow(x, exponent);
}

// Static specializations for frequently-used exponents, so that this gets
// turned into multiplications at compile time.

template<>
inline double Pow<-3>(double x) {
  return 1 / (x * x * x);
}

template<>
inline double Pow<-2>(double x) {
  return 1 / (x * x);
}

template<>
inline double Pow<-1>(double x) {
  return 1 / x;
}

template<>
inline double Pow<0>(double x) {
  return 1;
}

template<>
inline double Pow<1>(double x) {
  return x;
}

template<>
inline double Pow<2>(double x) {
  return x * x;
}

template<>
inline double Pow<3>(double x) {
  return x * x * x;
}

template<int exponent, typename D>
Exponentiation<Quantity<D>, exponent> Pow(
    Quantity<D> const& x) {
  return Exponentiation<Quantity<D>, exponent>(
      Pow<exponent>(x.magnitude_));
}

inline double Abs(double const x) {
  return std::abs(x);
}

template<typename D>
Quantity<D> Abs(Quantity<D> const& quantity) {
  return Quantity<D>(std::abs(quantity.magnitude_));
}

template<typename Q>
inline Q SIUnit() {
  return Q(1);
}

template<>
inline double SIUnit<double>() {
  return 1;
}

inline std::string FormatUnit(std::string const& name, int const exponent) {
  switch (exponent) {
    case 0:
      return "";
      break;
    case 1:
      return " " + name;
    default:
      return " " + name + "^" + std::to_string(exponent);
  }
}

inline std::string DebugString(double const number, int const precision) {
  char result[50];
#if OS_WIN
  unsigned int old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT);
  sprintf_s(result, ("%+." + std::to_string(precision) + "e").c_str(), number);
  _set_output_format(old_exponent_format);
#else
  snprintf(result, sizeof(result),
           ("%+." + std::to_string(precision) + "e").c_str(), number);
#endif
  return result;
}

template<typename D>
std::string DebugString(Quantity<D> const& quantity, int const precision) {
  return DebugString(quantity.magnitude_, precision) +
      FormatUnit("m", D::Length) + FormatUnit("kg", D::Mass) +
      FormatUnit("s", D::Time) + FormatUnit("A", D::Current) +
      FormatUnit("K", D::Temperature) + FormatUnit("mol", D::Amount) +
      FormatUnit("cd", D::LuminousIntensity) + FormatUnit("cycle", D::Winding) +
      FormatUnit("rad", D::Angle) + FormatUnit("sr", D::SolidAngle);
}

template<typename D>
std::ostream& operator<<(std::ostream& out, Quantity<D> const& quantity) {
  return out << DebugString(quantity);
}

}  // namespace quantities
}  // namespace principia
<commit_msg>Indent.<commit_after>#pragma once

#include <cmath>
#include <string>

#include "base/macros.hpp"

namespace principia {
namespace quantities {

template<int64_t LengthExponent, int64_t MassExponent, int64_t TimeExponent,
         int64_t CurrentExponent, int64_t TemperatureExponent,
         int64_t AmountExponent, int64_t LuminousIntensityExponent,
         int64_t WindingExponent, int64_t AngleExponent,
         int64_t SolidAngleExponent>
struct Dimensions {
  enum {
    Length            = LengthExponent,
    Mass              = MassExponent,
    Time              = TimeExponent,
    Current           = CurrentExponent,
    Temperature       = TemperatureExponent,
    Amount            = AmountExponent,
    LuminousIntensity = LuminousIntensityExponent,
    Winding           = WindingExponent,
    Angle             = AngleExponent,
    SolidAngle        = SolidAngleExponent
  };

  static int const kMinExponent = -16;
  static int const kMaxExponent = 15;
  static int const kExponentBits = 5;
  static int const kExponentMask = 0x1F;

  static_assert(LengthExponent >= kMinExponent &&
                LengthExponent <= kMaxExponent,
                "Invalid length exponent");
  static_assert(MassExponent >= kMinExponent &&
                MassExponent <= kMaxExponent,
                "Invalid mass exponent");
  static_assert(TimeExponent >= kMinExponent &&
                TimeExponent <= kMaxExponent,
                "Invalid time exponent");
  static_assert(CurrentExponent >= kMinExponent &&
                CurrentExponent <= kMaxExponent,
                "Invalid current exponent");
  static_assert(TemperatureExponent >= kMinExponent &&
                TemperatureExponent <= kMaxExponent,
                "Invalid temperature exponent");
  static_assert(AmountExponent >= kMinExponent &&
                AmountExponent <= kMaxExponent,
                "Invalid amount exponent");
  static_assert(LuminousIntensityExponent >= kMinExponent &&
                LuminousIntensityExponent <= kMaxExponent,
                "Invalid luminous intensity exponent");
  static_assert(AngleExponent >= kMinExponent &&
                AngleExponent <= kMaxExponent,
                "Invalid angle exponent");
  static_assert(SolidAngleExponent >= kMinExponent &&
                SolidAngleExponent <= kMaxExponent,
                "Invalid solid angle exponent");
  static_assert(WindingExponent >= kMinExponent &&
                WindingExponent <= kMaxExponent,
                "Invalid winding exponent");

  // The NOLINT are because glint is confused by the binary and.  I kid you not.
  static int64_t const representation =
      (LengthExponent & kExponentMask)                                 |  // NOLINT
      (MassExponent & kExponentMask)              << 1 * kExponentBits |  // NOLINT
      (TimeExponent & kExponentMask)              << 2 * kExponentBits |  // NOLINT
      (CurrentExponent & kExponentMask)           << 3 * kExponentBits |  // NOLINT
      (TemperatureExponent & kExponentMask)       << 4 * kExponentBits |  // NOLINT
      (AmountExponent & kExponentMask)            << 5 * kExponentBits |  // NOLINT
      (LuminousIntensityExponent & kExponentMask) << 6 * kExponentBits |  // NOLINT
      (AngleExponent & kExponentMask)             << 7 * kExponentBits |  // NOLINT
      (SolidAngleExponent & kExponentMask)        << 8 * kExponentBits |  // NOLINT
      (WindingExponent & kExponentMask)           << 9 * kExponentBits;   // NOLINT
};

namespace internal {
template<typename Q>
struct Collapse { using Type = Q; };
template<>
struct Collapse<Quantity<NoDimensions>> { using Type = double; };
template<typename Left, typename Right>
struct ProductGenerator {
  enum {
    Length            = Left::Dimensions::Length + Right::Dimensions::Length,
    Mass              = Left::Dimensions::Mass + Right::Dimensions::Mass,
    Time              = Left::Dimensions::Time + Right::Dimensions::Time,
    Current           = Left::Dimensions::Current + Right::Dimensions::Current,
    Temperature       = Left::Dimensions::Temperature +
                        Right::Dimensions::Temperature,
    Amount            = Left::Dimensions::Amount + Right::Dimensions::Amount,
    LuminousIntensity = Left::Dimensions::LuminousIntensity +
                        Right:: Dimensions::LuminousIntensity,
    Winding           = Left::Dimensions::Winding + Right::Dimensions::Winding,
    Angle             = Left::Dimensions::Angle + Right::Dimensions::Angle,
    SolidAngle        = Left::Dimensions::SolidAngle +
                        Right::Dimensions::SolidAngle
  };
  using Type = typename Collapse<
      Quantity<Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                          LuminousIntensity, Winding, Angle,
                          SolidAngle>>>::Type;
};
template<typename Left>
struct ProductGenerator<Left, double> { using Type = Left; };
template<typename Right>
struct ProductGenerator<double, Right> { using Type = Right; };
template<>
struct ProductGenerator<double, double> {
  using Type = double;
};
template<typename Left, typename Right>
struct QuotientGenerator {
  enum {
    Length            = Left::Dimensions::Length - Right::Dimensions::Length,
    Mass              = Left::Dimensions::Mass - Right::Dimensions::Mass,
    Time              = Left::Dimensions::Time - Right::Dimensions::Time,
    Current           = Left::Dimensions::Current - Right::Dimensions::Current,
    Temperature       = Left::Dimensions::Temperature -
                        Right::Dimensions::Temperature,
    Amount            = Left::Dimensions::Amount - Right::Dimensions::Amount,
    LuminousIntensity = Left::Dimensions::LuminousIntensity -
                        Right:: Dimensions::LuminousIntensity,
    Winding           = Left::Dimensions::Winding - Right::Dimensions::Winding,
    Angle             = Left::Dimensions::Angle - Right::Dimensions::Angle,
    SolidAngle        = Left::Dimensions::SolidAngle -
                        Right::Dimensions::SolidAngle
  };
  using Type = typename Collapse<
      Quantity<Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                          LuminousIntensity, Winding, Angle,
                          SolidAngle>>>::Type;
};
template<typename Left>
struct QuotientGenerator<Left, double> { using Type = Left; };
template<>
struct QuotientGenerator<double, double> {
  using Type = double;
};
template<typename Right>
struct QuotientGenerator<double, Right> {
  enum {
    Length            = -Right::Dimensions::Length,
    Mass              = -Right::Dimensions::Mass,
    Time              = -Right::Dimensions::Time,
    Current           = -Right::Dimensions::Current,
    Temperature       = -Right::Dimensions::Temperature,
    Amount            = -Right::Dimensions::Amount,
    LuminousIntensity = -Right::Dimensions::LuminousIntensity,
    Winding           = -Right::Dimensions::Winding,
    Angle             = -Right::Dimensions::Angle,
    SolidAngle        = -Right::Dimensions::SolidAngle
  };
  using Type = Quantity<
      Dimensions<Length, Mass, Time, Current, Temperature, Amount,
                 LuminousIntensity, Winding, Angle, SolidAngle>>;
};

template<typename T, int exponent>
struct ExponentiationGenerator<T, exponent, std::enable_if_t<(exponent > 1)>> {
  using Type = Product<typename ExponentiationGenerator<T, exponent - 1>::Type,
                       T>;
};

template<typename T, int exponent>
struct ExponentiationGenerator<T, exponent, std::enable_if_t<(exponent < 1)>>{
  using Type = Quotient<typename ExponentiationGenerator<T, exponent + 1>::Type,
                        T>;
};

template<typename T, int exponent>
struct ExponentiationGenerator<T, exponent, std::enable_if_t<(exponent == 1)>>{
  using Type = T;
};

}  // namespace internal

template<typename D>
inline Quantity<D>::Quantity() : magnitude_(0) {}

template<typename D>
inline Quantity<D>::Quantity(double const magnitude) : magnitude_(magnitude) {}

template<typename D>
inline Quantity<D>& Quantity<D>::operator+=(Quantity const& right) {
  magnitude_ += right.magnitude_;
  return *this;
}

template<typename D>
inline Quantity<D>& Quantity<D>::operator-=(Quantity const& right) {
  magnitude_ -= right.magnitude_;
  return *this;
}

template<typename D>
inline Quantity<D>& Quantity<D>::operator*=(double const right) {
  magnitude_ *= right;
  return *this;
}

template<typename D>
inline Quantity<D>& Quantity<D>::operator/=(double const right) {
  magnitude_ /= right;
  return *this;
}

// Additive group

template<typename D>
inline Quantity<D> Quantity<D>::operator+() const {
  return *this;
}

template<typename D>
inline Quantity<D> Quantity<D>::operator-() const {
  return Quantity(-magnitude_);
}

template<typename D>
inline Quantity<D> Quantity<D>::operator+(Quantity const& right) const {
  return Quantity(magnitude_ + right.magnitude_);
}

template<typename D>
inline Quantity<D> Quantity<D>::operator-(Quantity const& right) const {
  return Quantity(magnitude_ - right.magnitude_);
}

// Comparison operators

template<typename D>
inline bool Quantity<D>::operator>(Quantity const& right) const {
  return magnitude_ > right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator<(Quantity const& right) const {
  return magnitude_ < right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator>=(Quantity const& right) const {
  return magnitude_ >= right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator<=(Quantity const& right) const {
  return magnitude_ <= right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator==(Quantity const& right) const {
  return magnitude_ == right.magnitude_;
}

template<typename D>
inline bool Quantity<D>::operator!=(Quantity const& right) const {
  return magnitude_ != right.magnitude_;
}

template<typename D>
void Quantity<D>::WriteToMessage(
    not_null<serialization::Quantity*> const message) const {
  message->set_dimensions(D::representation);
  message->set_magnitude(magnitude_);
}

template<typename D>
Quantity<D> Quantity<D>::ReadFromMessage(
    serialization::Quantity const& message) {
  CHECK_EQ(D::representation, message.dimensions());
  return Quantity(message.magnitude());
}

// Multiplicative group

template<typename D>
inline Quantity<D> Quantity<D>::operator/(double const right) const {
  return Quantity(magnitude_ / right);
}

template<typename D>
inline Quantity<D> Quantity<D>::operator*(double const right) const {
  return Quantity(magnitude_ * right);
}

template<typename LDimensions, typename RDimensions>
inline internal::Product<Quantity<LDimensions>, Quantity<RDimensions>>
operator*(Quantity<LDimensions> const& left,
          Quantity<RDimensions> const& right) {
  return Product<Quantity<LDimensions>,
                 Quantity<RDimensions>>(left.magnitude_ * right.magnitude_);
}

template<typename LDimensions, typename RDimensions>
inline internal::Quotient<Quantity<LDimensions>, Quantity<RDimensions>>
operator/(Quantity<LDimensions> const& left,
          Quantity<RDimensions> const& right) {
  return Quotient<Quantity<LDimensions>,
                  Quantity<RDimensions>>(left.magnitude_ / right.magnitude_);
}

template<typename RDimensions>
FORCE_INLINE Quantity<RDimensions> operator*(
    double const left,
    Quantity<RDimensions> const& right) {
  return Quantity<RDimensions>(left * right.magnitude_);
}

template<typename RDimensions>
inline typename Quantity<RDimensions>::Inverse operator/(
    double const left,
    Quantity<RDimensions> const& right) {
  return typename Quantity<RDimensions>::Inverse(left / right.magnitude_);
}

template<int exponent>
inline double Pow(double x) {
  return std::pow(x, exponent);
}

// Static specializations for frequently-used exponents, so that this gets
// turned into multiplications at compile time.

template<>
inline double Pow<-3>(double x) {
  return 1 / (x * x * x);
}

template<>
inline double Pow<-2>(double x) {
  return 1 / (x * x);
}

template<>
inline double Pow<-1>(double x) {
  return 1 / x;
}

template<>
inline double Pow<0>(double x) {
  return 1;
}

template<>
inline double Pow<1>(double x) {
  return x;
}

template<>
inline double Pow<2>(double x) {
  return x * x;
}

template<>
inline double Pow<3>(double x) {
  return x * x * x;
}

template<int exponent, typename D>
Exponentiation<Quantity<D>, exponent> Pow(
    Quantity<D> const& x) {
  return Exponentiation<Quantity<D>, exponent>(
      Pow<exponent>(x.magnitude_));
}

inline double Abs(double const x) {
  return std::abs(x);
}

template<typename D>
Quantity<D> Abs(Quantity<D> const& quantity) {
  return Quantity<D>(std::abs(quantity.magnitude_));
}

template<typename Q>
inline Q SIUnit() {
  return Q(1);
}

template<>
inline double SIUnit<double>() {
  return 1;
}

inline std::string FormatUnit(std::string const& name, int const exponent) {
  switch (exponent) {
    case 0:
      return "";
      break;
    case 1:
      return " " + name;
    default:
      return " " + name + "^" + std::to_string(exponent);
  }
}

inline std::string DebugString(double const number, int const precision) {
  char result[50];
#if OS_WIN
  unsigned int old_exponent_format = _set_output_format(_TWO_DIGIT_EXPONENT);
  sprintf_s(result, ("%+." + std::to_string(precision) + "e").c_str(), number);
  _set_output_format(old_exponent_format);
#else
  snprintf(result, sizeof(result),
           ("%+." + std::to_string(precision) + "e").c_str(), number);
#endif
  return result;
}

template<typename D>
std::string DebugString(Quantity<D> const& quantity, int const precision) {
  return DebugString(quantity.magnitude_, precision) +
      FormatUnit("m", D::Length) + FormatUnit("kg", D::Mass) +
      FormatUnit("s", D::Time) + FormatUnit("A", D::Current) +
      FormatUnit("K", D::Temperature) + FormatUnit("mol", D::Amount) +
      FormatUnit("cd", D::LuminousIntensity) + FormatUnit("cycle", D::Winding) +
      FormatUnit("rad", D::Angle) + FormatUnit("sr", D::SolidAngle);
}

template<typename D>
std::ostream& operator<<(std::ostream& out, Quantity<D> const& quantity) {
  return out << DebugString(quantity);
}

}  // namespace quantities
}  // namespace principia
<|endoftext|>


<commit_before>#include <list>

#include <tst/set.hpp>
#include <tst/check.hpp>

#include <utki/linq.hpp>

#include <utki/config.hpp>

#if M_COMPILER != M_COMPILER_MSVC || M_COMPILER_MSVC_TOOLS_V >= 142

namespace{
tst::set set("linq", [](tst::suite& suite){
	suite.add(
		"linq_from_rvalue_select",
		[](){
			std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"}
			}};

			auto out = utki::linq(std::move(in)).select(
					[](auto v){
						auto r = std::make_pair(std::move(v.second), 13.4f);
						tst::check(v.second.empty(), SL);
						return r;
					}
				).get();

			static_assert(std::is_same<decltype(out), std::vector<std::pair<std::string, float>>>::value, "not same");

			decltype(out) expected = {{
				{"13", 13.4f},
				{"14", 13.4f},
				{"1", 13.4f}
			}};

			tst::check(out == expected, SL);
			tst::check(in.empty(), SL);
		}
	);

	suite.add(
		"linq_from_lvalue_select",
		[](){
			std::map<int, const std::string> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"}
			}};

			auto out = utki::linq(in).select(
					[](auto v, auto i){
						auto r = std::make_pair(std::move(v.second), i);
						tst::check(!v.second.empty(), SL);
						return r;
					}
				).get();

			// since original container is a map, the order of elements is sorted by map key
			decltype(out) expected = {{
				{"1", 0},
				{"13", 1},
				{"14", 2}
			}};

			tst::check(out == expected, [&](auto&o){o << "out.size() = " << out.size() << std::endl;}, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.begin()->second.empty(), SL);
		}
	);

	suite.add(
		"linq_from_const_lvalue_select",
		[](){
			const std::list<std::pair<int, const std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"}
			}};

			auto out = utki::linq(in).select(
					[](auto v){
						auto r = std::make_pair(std::move(v.second), 13.4f);
						tst::check(!v.second.empty(), SL);
						return r;
					}
				).get();

			decltype(out) expected = {{
				{"13", 13.4f},
				{"14", 13.4f},
				{"1", 13.4f}
			}};

			tst::check(out == expected, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.front().second.empty(), SL);
		}
	);

	suite.add(
		"linq_from_rvalue_group_by",
		[](){
			std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"},
				{132, "13"},
				{15, "15"},
				{133, "13"},
				{11, "1"}
			}};

			auto out = utki::linq(std::move(in)).select(
					[](auto v, auto i){
						auto r = std::make_tuple(std::move(v.second), v.first, i);
						tst::check(v.second.empty(), SL);
						return r;
					}
				).group_by(
					[](const auto& v)->const std::string&{
						return std::get<0>(v);
					}
				).get();

			decltype(out) expected = {{
				{"1", {
					{"1", 1, 2}, {"1", 11, 6}
				} },
				{"13", {
					{"13", 13, 0}, {"13", 132, 3}, {"13", 133, 5}
				} },
				{"14", {
					{"14", 14, 1}
				} },
				{"15", {
					{"15", 15, 4}
				} }
			}};

			tst::check(!out.empty(), SL);
			tst::check(out == expected, SL);
			tst::check(in.empty(), SL);
		}
	);

	suite.add(
		"linq_from_const_lvalue_where",
		[](){
			const std::list<std::pair<int, const std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"},
				{13, "13_2"},
				{3, "3"},
				{13, "13_3"}
			}};

			auto out = utki::linq(in).where([](const decltype(in)::value_type& v){return v.first == 13;}).get();

			decltype(out) expected = {{
				{13, "13"},
				{13, "13_2"},
				{13, "13_3"}
			}};

			tst::check(out == expected, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.front().second.empty(), SL);
		}
	);

	suite.add(
		"linq_from_const_lvalue_group_by_where",
		[](){
			const std::list<std::pair<int, const std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"},
				{13, "13_2"},
				{3, "3"},
				{3, "3_2"}
			}};

			auto out = utki::linq(in).group_by([](const auto& v){return v.first;}).where([](const auto& v){return v.second.size() == 2;}).get();

			tst::check(!in.empty(), SL);
			tst::check(!in.front().second.empty(), SL);

			tst::check(out.size() == 2, [&](auto&o){o << "out.size() = " << out.size();}, SL);
			tst::check(out.begin()->first == 3, [&](auto&o){o << "out.begin()->first = " << out.begin()->first;}, SL);
			tst::check(std::next(out.begin())->first == 13, [&](auto&o){o << "std::next(out.begin())->first = " << std::next(out.begin())->first;}, SL);
			tst::check(out.begin()->second.size() == 2, [&](auto&o){o << "out.begin()->second.size() = " << out.begin()->second.size();}, SL);
		}
	);

	suite.add(
		"linq_from_rvalue_order_by",
		[](){
			std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"},
				{5, "asd"},
				{1, "1"}
			}};

			auto out = utki::linq(std::move(in)).order_by(
					[](const auto& v) -> const int&{
						return v.first;
					}
				).get();

			static_assert(std::is_same<decltype(out), decltype(in)>::value, "not same");

			decltype(out) expected = {{
				{1, "1"},
				{5, "asd"},
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"}
			}};

#ifdef DEBUG
			for(auto& e : out){
					LOG([&](auto&o){o << "e = " << e.first << " " << e.second << std::endl;})
			}
#endif

			tst::check(out == expected, SL);
			tst::check(in.empty(), SL);
		}
	);

	suite.add(
		"linq_from_lvalue_order_by",
		[](){
			std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"},
				{5, "asd"},
				{1, "1"}
			}};

			auto out = utki::linq(in).order_by(
					[](const auto& v) -> const int&{
						return v.first;
					}
				).get();

			static_assert(std::is_same<decltype(out), decltype(in)>::value, "not same");

			decltype(out) expected = {{
				{1, "1"},
				{5, "asd"},
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"}
			}};

#ifdef DEBUG
			for(auto& e : out){
				LOG([&](auto&o){o << "e = " << e.first << " " << e.second << std::endl;})
			}
#endif

			tst::check(out == expected, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.begin()->second.empty(), SL);
		}
	);

	suite.add(
		"linq_from_const_lvalue_order_by",
		[](){
			const std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"},
				{5, "asd"},
				{1, "1"}
			}};

			auto out = utki::linq(in).order_by(
					[](const auto& v) -> const int&{
						return v.first;
					}
				).get();

			static_assert(std::is_same<decltype(out), std::remove_const<decltype(in)>::type>::value, "not same");

			decltype(out) expected = {{
				{1, "1"},
				{5, "asd"},
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"}
			}};

#ifdef DEBUG
			for(auto& e : out){
				LOG([&](auto&o){o << "e = " << e.first << " " << e.second << std::endl;})
			}
#endif

			tst::check(out == expected, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.begin()->second.empty(), SL);
		}
	);
});
}

#endif // ~ non-MSVC compiler or MSVC compiler tools >= v142
<commit_msg>add linq test<commit_after>#include <list>

#include <tst/set.hpp>
#include <tst/check.hpp>

#include <utki/linq.hpp>

#include <utki/config.hpp>

#if M_COMPILER != M_COMPILER_MSVC || M_COMPILER_MSVC_TOOLS_V >= 142

namespace{
tst::set set("linq", [](tst::suite& suite){
	suite.add(
		"linq_from_rvalue_select",
		[](){
			std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"}
			}};

			auto out = utki::linq(std::move(in)).select(
					[](auto v){
						auto r = std::make_pair(std::move(v.second), 13.4f);
						tst::check(v.second.empty(), SL);
						return r;
					}
				).get();

			static_assert(std::is_same<decltype(out), std::vector<std::pair<std::string, float>>>::value, "not same");

			decltype(out) expected = {{
				{"13", 13.4f},
				{"14", 13.4f},
				{"1", 13.4f}
			}};

			tst::check(out == expected, SL);
			tst::check(in.empty(), SL);
		}
	);

	suite.add(
		"linq_from_lvalue_select",
		[](){
			std::map<int, const std::string> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"}
			}};

			auto out = utki::linq(in).select(
					[](auto v, auto i){
						auto r = std::make_pair(std::move(v.second), i);
						tst::check(!v.second.empty(), SL);
						return r;
					}
				).get();

			// since original container is a map, the order of elements is sorted by map key
			decltype(out) expected = {{
				{"1", 0},
				{"13", 1},
				{"14", 2}
			}};

			tst::check(out == expected, [&](auto&o){o << "out.size() = " << out.size() << std::endl;}, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.begin()->second.empty(), SL);
		}
	);

	suite.add(
		"linq_from_const_lvalue_select",
		[](){
			const std::list<std::pair<int, const std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"}
			}};

			auto out = utki::linq(in).select(
					[](auto v){
						auto r = std::make_pair(std::move(v.second), 13.4f);
						tst::check(!v.second.empty(), SL);
						return r;
					}
				).get();

			decltype(out) expected = {{
				{"13", 13.4f},
				{"14", 13.4f},
				{"1", 13.4f}
			}};

			tst::check(out == expected, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.front().second.empty(), SL);
		}
	);

	suite.add(
		"linq_from_rvalue_group_by",
		[](){
			std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"},
				{132, "13"},
				{15, "15"},
				{133, "13"},
				{11, "1"}
			}};

			auto out = utki::linq(std::move(in)).select(
					[](auto v, auto i){
						auto r = std::make_tuple(std::move(v.second), v.first, i);
						tst::check(v.second.empty(), SL);
						return r;
					}
				).group_by(
					[](const auto& v)->const std::string&{
						return std::get<0>(v);
					}
				).get();

			decltype(out) expected = {{
				{"1", {
					{"1", 1, 2}, {"1", 11, 6}
				} },
				{"13", {
					{"13", 13, 0}, {"13", 132, 3}, {"13", 133, 5}
				} },
				{"14", {
					{"14", 14, 1}
				} },
				{"15", {
					{"15", 15, 4}
				} }
			}};

			tst::check(!out.empty(), SL);
			tst::check(out == expected, SL);
			tst::check(in.empty(), SL);
		}
	);

	suite.add(
		"linq_from_const_lvalue_where",
		[](){
			const std::list<std::pair<int, const std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"},
				{13, "13_2"},
				{3, "3"},
				{13, "13_3"}
			}};

			auto out = utki::linq(in).where([](const decltype(in)::value_type& v){return v.first == 13;}).get();

			decltype(out) expected = {{
				{13, "13"},
				{13, "13_2"},
				{13, "13_3"}
			}};

			tst::check(out == expected, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.front().second.empty(), SL);
		}
	);

	suite.add(
		"linq_from_const_lvalue_group_by_where",
		[](){
			const std::list<std::pair<int, const std::string>> in = {{
				{13, "13"},
				{14, "14"},
				{1, "1"},
				{13, "13_2"},
				{3, "3"},
				{3, "3_2"}
			}};

			auto out = utki::linq(in).group_by([](const auto& v){return v.first;}).where([](const auto& v){return v.second.size() == 2;}).get();

			tst::check(!in.empty(), SL);
			tst::check(!in.front().second.empty(), SL);

			tst::check(out.size() == 2, [&](auto&o){o << "out.size() = " << out.size();}, SL);
			tst::check(out.begin()->first == 3, [&](auto&o){o << "out.begin()->first = " << out.begin()->first;}, SL);
			tst::check(std::next(out.begin())->first == 13, [&](auto&o){o << "std::next(out.begin())->first = " << std::next(out.begin())->first;}, SL);
			tst::check(out.begin()->second.size() == 2, [&](auto&o){o << "out.begin()->second.size() = " << out.begin()->second.size();}, SL);
		}
	);

	suite.add(
		"linq_from_rvalue_order_by",
		[](){
			std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"},
				{5, "asd"},
				{1, "1"}
			}};

			auto out = utki::linq(std::move(in)).order_by(
					[](const auto& v) -> const int&{
						return v.first;
					}
				).get();

			static_assert(std::is_same<decltype(out), decltype(in)>::value, "not same");

			decltype(out) expected = {{
				{1, "1"},
				{5, "asd"},
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"}
			}};

#ifdef DEBUG
			for(auto& e : out){
					LOG([&](auto&o){o << "e = " << e.first << " " << e.second << std::endl;})
			}
#endif

			tst::check(out == expected, SL);
			tst::check(in.empty(), SL);
		}
	);

	suite.add(
		"linq_from_lvalue_order_by",
		[](){
			std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"},
				{5, "asd"},
				{1, "1"}
			}};

			auto out = utki::linq(in).order_by(
					[](const auto& v) -> const int&{
						return v.first;
					}
				).get();

			static_assert(std::is_same<decltype(out), decltype(in)>::value, "not same");

			decltype(out) expected = {{
				{1, "1"},
				{5, "asd"},
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"}
			}};

#ifdef DEBUG
			for(auto& e : out){
				LOG([&](auto&o){o << "e = " << e.first << " " << e.second << std::endl;})
			}
#endif

			tst::check(out == expected, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.begin()->second.empty(), SL);
		}
	);

	suite.add(
		"linq_from_const_lvalue_order_by",
		[](){
			const std::vector<std::pair<int, std::string>> in = {{
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"},
				{5, "asd"},
				{1, "1"}
			}};

			auto out = utki::linq(in).order_by(
					[](const auto& v) -> const int&{
						return v.first;
					}
				).get();

			static_assert(std::is_same<decltype(out), std::remove_const<decltype(in)>::type>::value, "not same");

			decltype(out) expected = {{
				{1, "1"},
				{5, "asd"},
				{13, "13"},
				{14, "hgb"},
				{14, "asdh"}
			}};

#ifdef DEBUG
			for(auto& e : out){
				LOG([&](auto&o){o << "e = " << e.first << " " << e.second << std::endl;})
			}
#endif

			tst::check(out == expected, SL);
			tst::check(!in.empty(), SL);
			tst::check(!in.begin()->second.empty(), SL);
		}
	);

	suite.add(
		"select_shared_ptr",
		[](){
			struct test_struct{
				bool& destroyed;
				test_struct(bool& destroyed) : destroyed(destroyed){}
				~test_struct()noexcept(false){
					this->destroyed = true;
				}
			};

			bool destroyed = false;

			struct wrapper{
				std::shared_ptr<test_struct> ts;
				int dummy;

				~wrapper()noexcept(false){}
			};

			std::vector<wrapper> vec{
				{ std::make_shared<test_struct>(destroyed), 10 },
				{ std::make_shared<test_struct>(destroyed), 13 }
			};

			auto res = utki::linq(vec).select([](const auto& i) -> std::shared_ptr<const test_struct> {
				return i.ts;
			}).get();

			vec.clear();

			tst::check(!destroyed, SL);

			res.clear();

			tst::check(destroyed, SL);
		}
	);
});
}

#endif // ~ non-MSVC compiler or MSVC compiler tools >= v142
<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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 "DataStructures/QueryEdge.h"
#include "DataStructures/SharedMemoryFactory.h"
#include "DataStructures/SharedMemoryVectorWrapper.h"
#include "DataStructures/StaticGraph.h"
#include "DataStructures/StaticRTree.h"
#include "Server/DataStructures/BaseDataFacade.h"
#include "Server/DataStructures/SharedDataType.h"
#include "Util/BoostFileSystemFix.h"
#include "Util/ProgramOptions.h"
#include "Util/SimpleLogger.h"
#include "Util/UUID.h"
#include "typedefs.h"

#include <boost/integer.hpp>
#include <boost/filesystem/fstream.hpp>

#include <string>
#include <vector>

int main( const int argc, const char * argv[] ) {
    try {
        LogPolicy::GetInstance().Unmute();
        SimpleLogger().Write() << "Checking input parameters";

        bool use_shared_memory = false;
        std::string ip_address;
        int ip_port, requested_num_threads;

        ServerPaths server_paths;
        if( !GenerateServerProgramOptions(
                argc,
                argv,
                server_paths,
                ip_address,
                ip_port,
                requested_num_threads,
                use_shared_memory
             )
        ) {
            return 0;
        }
        if( server_paths.find("hsgrdata") == server_paths.end() ) {
            throw OSRMException("no hsgr file given in ini file");
        }
        if( server_paths.find("ramindex") == server_paths.end() ) {
            throw OSRMException("no ram index file given in ini file");
        }
        if( server_paths.find("fileindex") == server_paths.end() ) {
            throw OSRMException("no leaf index file given in ini file");
        }
        if( server_paths.find("nodesdata") == server_paths.end() ) {
            throw OSRMException("no nodes file given in ini file");
        }
        if( server_paths.find("edgesdata") == server_paths.end() ) {
            throw OSRMException("no edges file given in ini file");
        }
        if( server_paths.find("namesdata") == server_paths.end() ) {
            throw OSRMException("no names file given in ini file");
        }

        ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & hsgr_path = paths_iterator->second;
        paths_iterator = server_paths.find("timestamp");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & timestamp_path = paths_iterator->second;
        paths_iterator = server_paths.find("ramindex");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & ram_index_path = paths_iterator->second;
        // paths_iterator = server_paths.find("fileindex");
        // BOOST_ASSERT(server_paths.end() != paths_iterator);
        // const boost::filesystem::path & file_index_path = paths_iterator->second;
        paths_iterator = server_paths.find("nodesdata");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & nodes_data_path = paths_iterator->second;
        paths_iterator = server_paths.find("edgesdata");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & edges_data_path = paths_iterator->second;
        paths_iterator = server_paths.find("namesdata");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & names_data_path = paths_iterator->second;

        // Allocate a memory layout in shared memory //
          SharedMemory * layout_memory = SharedMemoryFactory::Get(
            LAYOUT_1,
            sizeof(SharedDataLayout)
        );
        SharedDataLayout * shared_layout_ptr = static_cast<SharedDataLayout *>(
            layout_memory->Ptr()
        );
        shared_layout_ptr = new(layout_memory->Ptr()) SharedDataLayout();

        //                                                             //
        // collect number of elements to store in shared memory object //
        //                                                             //
        SimpleLogger().Write() << "Collecting files sizes";
        // number of entries in name index
        boost::filesystem::ifstream name_stream(
            names_data_path, std::ios::binary
        );
        unsigned name_index_size = 0;
        name_stream.read((char *)&name_index_size, sizeof(unsigned));
        shared_layout_ptr->name_index_list_size = name_index_size;
        // SimpleLogger().Write() << "name index size: " << shared_layout_ptr->name_index_list_size;
        BOOST_ASSERT_MSG(0 != shared_layout_ptr->name_index_list_size, "name file broken");

        unsigned number_of_chars = 0;
        name_stream.read((char *)&number_of_chars, sizeof(unsigned));
        shared_layout_ptr->name_char_list_size = number_of_chars;
        // SimpleLogger().Write() << "name char size: " << shared_layout_ptr->name_char_list_size;

        //Loading information for original edges
        boost::filesystem::ifstream edges_input_stream(
            edges_data_path,
            std::ios::binary
        );
        unsigned number_of_original_edges = 0;
        edges_input_stream.read((char*)&number_of_original_edges, sizeof(unsigned));
        SimpleLogger().Write(logDEBUG) <<
            "number of edges: " << number_of_original_edges;

        shared_layout_ptr->via_node_list_size = number_of_original_edges;
        shared_layout_ptr->name_id_list_size = number_of_original_edges;
        shared_layout_ptr->turn_instruction_list_size = number_of_original_edges;

        SimpleLogger().Write(logDEBUG) << "noted number of edges";

        SimpleLogger().Write(logDEBUG) << "loading hsgr from " << hsgr_path.string();
        boost::filesystem::ifstream hsgr_input_stream(
            hsgr_path,
            std::ios::binary
        );

        UUID uuid_loaded, uuid_orig;
        hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
        if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
            SimpleLogger().Write(logWARNING) <<
                ".hsgr was prepared with different build. "
                "Reprocess to get rid of this warning.";
        } else {
            SimpleLogger().Write() << "UUID checked out ok";
        }

        // load checksum
        unsigned checksum = 0;
        hsgr_input_stream.read((char*)&checksum, sizeof(unsigned) );
        SimpleLogger().Write() << "checksum: " << checksum;
        shared_layout_ptr->checksum = checksum;
        SimpleLogger().Write(logDEBUG) << "noted checksum";
        // load graph node size
        unsigned number_of_graph_nodes = 0;
        hsgr_input_stream.read(
            (char*) &number_of_graph_nodes,
            sizeof(unsigned)
        );
        SimpleLogger().Write(logDEBUG) << "number of nodes: " << number_of_graph_nodes;
        BOOST_ASSERT_MSG(
            (0 != number_of_graph_nodes),
            "number of nodes is zero"
        );
        shared_layout_ptr->graph_node_list_size = number_of_graph_nodes;

        // load graph edge size
        unsigned number_of_graph_edges = 0;
        hsgr_input_stream.read( (char*) &number_of_graph_edges, sizeof(unsigned) );
        SimpleLogger().Write() << "number of graph edges: " << number_of_graph_edges;
        BOOST_ASSERT_MSG( 0 != number_of_graph_edges, "number of graph edges is zero");
        shared_layout_ptr->graph_edge_list_size = number_of_graph_edges;

        // load rsearch tree size
        SimpleLogger().Write(logDEBUG) << "loading r-tree search list size";
        boost::filesystem::ifstream tree_node_file(
            ram_index_path,
            std::ios::binary
        );

        uint32_t tree_size = 0;
        tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
        shared_layout_ptr->r_search_tree_size = tree_size;

        //load timestamp size
        SimpleLogger().Write(logDEBUG) << "Loading timestamp";
        std::string m_timestamp;
        if( boost::filesystem::exists(timestamp_path) ) {
            boost::filesystem::ifstream timestampInStream( timestamp_path );
            if(!timestampInStream) {
                SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
            }
            getline(timestampInStream, m_timestamp);
            timestampInStream.close();
        }
        if(m_timestamp.empty()) {
            m_timestamp = "n/a";
        }
        if(25 < m_timestamp.length()) {
            m_timestamp.resize(25);
        }
        shared_layout_ptr->timestamp_length = m_timestamp.length();

        //load coordinate size
        SimpleLogger().Write() <<
            "Loading coordinates list from " << nodes_data_path.string();
        boost::filesystem::ifstream nodes_input_stream(
            nodes_data_path,
            std::ios::binary
        );
        unsigned coordinate_list_size = 0;
        nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
        shared_layout_ptr->coordinate_list_size = coordinate_list_size;

        // allocate shared memory block
        SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes";
        SharedMemory * shared_memory = SharedMemoryFactory::Get(
            DATA_1,
            shared_layout_ptr->GetSizeOfLayout()
        );
        char * shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());

        // read actual data into shared memory object //
        // Loading street names
        SimpleLogger().Write() << "Loading names index and chars from: " << names_data_path.string();
        unsigned * name_index_ptr = (unsigned*)(
            shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset()
        );
        SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_index_list_size*sizeof(unsigned);

        name_stream.read(
            (char*)name_index_ptr,
            shared_layout_ptr->name_index_list_size*sizeof(unsigned)
        );

        SimpleLogger().Write(logDEBUG) << "Loading names char list";
        SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_char_list_size*sizeof(char);
        char * name_char_ptr = shared_memory_ptr + shared_layout_ptr->GetNameListOffset();
        name_stream.read(
            name_char_ptr,
            shared_layout_ptr->name_char_list_size*sizeof(char)
        );
        name_stream.close();

        //load original edge information
        SimpleLogger().Write() <<
            "Loading via node, coordinates and turn instruction lists from: " <<
            edges_data_path.string();

        NodeID * via_node_ptr = (NodeID *)(
            shared_memory_ptr + shared_layout_ptr->GetViaNodeListOffset()
        );

        unsigned * name_id_ptr = (unsigned *)(
            shared_memory_ptr + shared_layout_ptr->GetNameIDListOffset()
        );

        TurnInstruction * turn_instructions_ptr = (TurnInstruction *)(
            shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset()
        );

        OriginalEdgeData current_edge_data;
        for(unsigned i = 0; i < number_of_original_edges; ++i) {
            // SimpleLogger().Write() << i << "/" << number_of_edges;
            edges_input_stream.read(
                (char*)&(current_edge_data),
                sizeof(OriginalEdgeData)
            );
            via_node_ptr[i] = current_edge_data.viaNode;
            name_id_ptr[i]  = current_edge_data.nameID;
            turn_instructions_ptr[i] = current_edge_data.turnInstruction;
        }
        edges_input_stream.close();

        // Loading list of coordinates
        FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)(
            shared_memory_ptr + shared_layout_ptr->GetCoordinateListOffset()
        );

        NodeInfo current_node;
        for(unsigned i = 0; i < coordinate_list_size; ++i) {
            nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
            coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
        }
        nodes_input_stream.close();

        //store timestamp
        char * timestamp_ptr = static_cast<char *>(
            shared_memory_ptr + shared_layout_ptr->GetTimeStampOffset()
        );
        std::copy(
            m_timestamp.c_str(),
            m_timestamp.c_str()+m_timestamp.length(),
            timestamp_ptr
        );

        // store search tree portion of rtree
        char * rtree_ptr = static_cast<char *>(
            shared_memory_ptr + shared_layout_ptr->GetRSearchTreeOffset()
        );

        tree_node_file.read(rtree_ptr, sizeof(RTreeNode)*tree_size);
        tree_node_file.close();

        // load the nodes of the search graph
        QueryGraph::_StrNode * graph_node_list_ptr = (QueryGraph::_StrNode*)(
            shared_memory_ptr + shared_layout_ptr->GetGraphNodeListOffset()
        );
        hsgr_input_stream.read(
            (char*) graph_node_list_ptr,
            shared_layout_ptr->graph_node_list_size*sizeof(QueryGraph::_StrNode)
        );

        // load the edges of the search graph
        QueryGraph::_StrEdge * graph_edge_list_ptr = (QueryGraph::_StrEdge *)(
            shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffsett()
        );
        hsgr_input_stream.read(
            (char*) graph_edge_list_ptr,
            shared_layout_ptr->graph_edge_list_size*sizeof(QueryGraph::_StrEdge)
        );
        hsgr_input_stream.close();

        SimpleLogger().Write() << "all data loaded. pressing a key deallocates memory";
        std::cin.get();

    } catch(const std::exception & e) {
        SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
    }

    return 0;
}
<commit_msg>set todo marker<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
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 "DataStructures/QueryEdge.h"
#include "DataStructures/SharedMemoryFactory.h"
#include "DataStructures/SharedMemoryVectorWrapper.h"
#include "DataStructures/StaticGraph.h"
#include "DataStructures/StaticRTree.h"
#include "Server/DataStructures/BaseDataFacade.h"
#include "Server/DataStructures/SharedDataType.h"
#include "Util/BoostFileSystemFix.h"
#include "Util/ProgramOptions.h"
#include "Util/SimpleLogger.h"
#include "Util/UUID.h"
#include "typedefs.h"

#include <boost/integer.hpp>
#include <boost/filesystem/fstream.hpp>

#include <string>
#include <vector>

int main( const int argc, const char * argv[] ) {
    try {
        LogPolicy::GetInstance().Unmute();
        SimpleLogger().Write() << "Checking input parameters";

        bool use_shared_memory = false;
        std::string ip_address;
        int ip_port, requested_num_threads;

        ServerPaths server_paths;
        if( !GenerateServerProgramOptions(
                argc,
                argv,
                server_paths,
                ip_address,
                ip_port,
                requested_num_threads,
                use_shared_memory
             )
        ) {
            return 0;
        }
        if( server_paths.find("hsgrdata") == server_paths.end() ) {
            throw OSRMException("no hsgr file given in ini file");
        }
        if( server_paths.find("ramindex") == server_paths.end() ) {
            throw OSRMException("no ram index file given in ini file");
        }
        if( server_paths.find("fileindex") == server_paths.end() ) {
            throw OSRMException("no leaf index file given in ini file");
        }
        if( server_paths.find("nodesdata") == server_paths.end() ) {
            throw OSRMException("no nodes file given in ini file");
        }
        if( server_paths.find("edgesdata") == server_paths.end() ) {
            throw OSRMException("no edges file given in ini file");
        }
        if( server_paths.find("namesdata") == server_paths.end() ) {
            throw OSRMException("no names file given in ini file");
        }

        ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & hsgr_path = paths_iterator->second;
        paths_iterator = server_paths.find("timestamp");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & timestamp_path = paths_iterator->second;
        paths_iterator = server_paths.find("ramindex");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & ram_index_path = paths_iterator->second;
        // paths_iterator = server_paths.find("fileindex");
        // BOOST_ASSERT(server_paths.end() != paths_iterator);
        // const boost::filesystem::path & file_index_path = paths_iterator->second;
        paths_iterator = server_paths.find("nodesdata");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & nodes_data_path = paths_iterator->second;
        paths_iterator = server_paths.find("edgesdata");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & edges_data_path = paths_iterator->second;
        paths_iterator = server_paths.find("namesdata");
        BOOST_ASSERT(server_paths.end() != paths_iterator);
        const boost::filesystem::path & names_data_path = paths_iterator->second;

        // Allocate a memory layout in shared memory //
          SharedMemory * layout_memory = SharedMemoryFactory::Get(
            LAYOUT_1,
            sizeof(SharedDataLayout)
        );
        SharedDataLayout * shared_layout_ptr = static_cast<SharedDataLayout *>(
            layout_memory->Ptr()
        );
        shared_layout_ptr = new(layout_memory->Ptr()) SharedDataLayout();

        //                                                             //
        // collect number of elements to store in shared memory object //
        //                                                             //
        SimpleLogger().Write() << "Collecting files sizes";
        // number of entries in name index
        boost::filesystem::ifstream name_stream(
            names_data_path, std::ios::binary
        );
        unsigned name_index_size = 0;
        name_stream.read((char *)&name_index_size, sizeof(unsigned));
        shared_layout_ptr->name_index_list_size = name_index_size;
        // SimpleLogger().Write() << "name index size: " << shared_layout_ptr->name_index_list_size;
        BOOST_ASSERT_MSG(0 != shared_layout_ptr->name_index_list_size, "name file broken");

        unsigned number_of_chars = 0;
        name_stream.read((char *)&number_of_chars, sizeof(unsigned));
        shared_layout_ptr->name_char_list_size = number_of_chars;
        // SimpleLogger().Write() << "name char size: " << shared_layout_ptr->name_char_list_size;

        //Loading information for original edges
        boost::filesystem::ifstream edges_input_stream(
            edges_data_path,
            std::ios::binary
        );
        unsigned number_of_original_edges = 0;
        edges_input_stream.read((char*)&number_of_original_edges, sizeof(unsigned));
        SimpleLogger().Write(logDEBUG) <<
            "number of edges: " << number_of_original_edges;

        shared_layout_ptr->via_node_list_size = number_of_original_edges;
        shared_layout_ptr->name_id_list_size = number_of_original_edges;
        shared_layout_ptr->turn_instruction_list_size = number_of_original_edges;

        SimpleLogger().Write(logDEBUG) << "noted number of edges";

        SimpleLogger().Write(logDEBUG) << "loading hsgr from " << hsgr_path.string();
        boost::filesystem::ifstream hsgr_input_stream(
            hsgr_path,
            std::ios::binary
        );

        UUID uuid_loaded, uuid_orig;
        hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
        if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
            SimpleLogger().Write(logWARNING) <<
                ".hsgr was prepared with different build. "
                "Reprocess to get rid of this warning.";
        } else {
            SimpleLogger().Write() << "UUID checked out ok";
        }

        // load checksum
        unsigned checksum = 0;
        hsgr_input_stream.read((char*)&checksum, sizeof(unsigned) );
        SimpleLogger().Write() << "checksum: " << checksum;
        shared_layout_ptr->checksum = checksum;
        SimpleLogger().Write(logDEBUG) << "noted checksum";
        // load graph node size
        unsigned number_of_graph_nodes = 0;
        hsgr_input_stream.read(
            (char*) &number_of_graph_nodes,
            sizeof(unsigned)
        );
        SimpleLogger().Write(logDEBUG) << "number of nodes: " << number_of_graph_nodes;
        BOOST_ASSERT_MSG(
            (0 != number_of_graph_nodes),
            "number of nodes is zero"
        );
        shared_layout_ptr->graph_node_list_size = number_of_graph_nodes;

        // load graph edge size
        unsigned number_of_graph_edges = 0;
        hsgr_input_stream.read( (char*) &number_of_graph_edges, sizeof(unsigned) );
        SimpleLogger().Write() << "number of graph edges: " << number_of_graph_edges;
        BOOST_ASSERT_MSG( 0 != number_of_graph_edges, "number of graph edges is zero");
        shared_layout_ptr->graph_edge_list_size = number_of_graph_edges;

        // load rsearch tree size
        SimpleLogger().Write(logDEBUG) << "loading r-tree search list size";
        boost::filesystem::ifstream tree_node_file(
            ram_index_path,
            std::ios::binary
        );

        uint32_t tree_size = 0;
        tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
        shared_layout_ptr->r_search_tree_size = tree_size;

        //load timestamp size
        SimpleLogger().Write(logDEBUG) << "Loading timestamp";
        std::string m_timestamp;
        if( boost::filesystem::exists(timestamp_path) ) {
            boost::filesystem::ifstream timestampInStream( timestamp_path );
            if(!timestampInStream) {
                SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
            }
            getline(timestampInStream, m_timestamp);
            timestampInStream.close();
        }
        if(m_timestamp.empty()) {
            m_timestamp = "n/a";
        }
        if(25 < m_timestamp.length()) {
            m_timestamp.resize(25);
        }
        shared_layout_ptr->timestamp_length = m_timestamp.length();

        //load coordinate size
        SimpleLogger().Write() <<
            "Loading coordinates list from " << nodes_data_path.string();
        boost::filesystem::ifstream nodes_input_stream(
            nodes_data_path,
            std::ios::binary
        );
        unsigned coordinate_list_size = 0;
        nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
        shared_layout_ptr->coordinate_list_size = coordinate_list_size;

        // allocate shared memory block
        SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes";
        SharedMemory * shared_memory = SharedMemoryFactory::Get(
            DATA_1,
            shared_layout_ptr->GetSizeOfLayout()
        );
        char * shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());

        // read actual data into shared memory object //
        // Loading street names
        SimpleLogger().Write() << "Loading names index and chars from: " << names_data_path.string();
        unsigned * name_index_ptr = (unsigned*)(
            shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset()
        );
        SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_index_list_size*sizeof(unsigned);

        name_stream.read(
            (char*)name_index_ptr,
            shared_layout_ptr->name_index_list_size*sizeof(unsigned)
        );

        SimpleLogger().Write(logDEBUG) << "Loading names char list";
        SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_char_list_size*sizeof(char);
        char * name_char_ptr = shared_memory_ptr + shared_layout_ptr->GetNameListOffset();
        name_stream.read(
            name_char_ptr,
            shared_layout_ptr->name_char_list_size*sizeof(char)
        );
        name_stream.close();

        //load original edge information
        SimpleLogger().Write() <<
            "Loading via node, coordinates and turn instruction lists from: " <<
            edges_data_path.string();

        NodeID * via_node_ptr = (NodeID *)(
            shared_memory_ptr + shared_layout_ptr->GetViaNodeListOffset()
        );

        unsigned * name_id_ptr = (unsigned *)(
            shared_memory_ptr + shared_layout_ptr->GetNameIDListOffset()
        );

        TurnInstruction * turn_instructions_ptr = (TurnInstruction *)(
            shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset()
        );

        OriginalEdgeData current_edge_data;
        for(unsigned i = 0; i < number_of_original_edges; ++i) {
            // SimpleLogger().Write() << i << "/" << number_of_edges;
            edges_input_stream.read(
                (char*)&(current_edge_data),
                sizeof(OriginalEdgeData)
            );
            via_node_ptr[i] = current_edge_data.viaNode;
            name_id_ptr[i]  = current_edge_data.nameID;
            turn_instructions_ptr[i] = current_edge_data.turnInstruction;
        }
        edges_input_stream.close();

        // Loading list of coordinates
        FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)(
            shared_memory_ptr + shared_layout_ptr->GetCoordinateListOffset()
        );

        NodeInfo current_node;
        for(unsigned i = 0; i < coordinate_list_size; ++i) {
            nodes_input_stream.read((char *)&current_node, sizeof(NodeInfo));
            coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
        }
        nodes_input_stream.close();

        //store timestamp
        char * timestamp_ptr = static_cast<char *>(
            shared_memory_ptr + shared_layout_ptr->GetTimeStampOffset()
        );
        std::copy(
            m_timestamp.c_str(),
            m_timestamp.c_str()+m_timestamp.length(),
            timestamp_ptr
        );

        // store search tree portion of rtree
        char * rtree_ptr = static_cast<char *>(
            shared_memory_ptr + shared_layout_ptr->GetRSearchTreeOffset()
        );

        tree_node_file.read(rtree_ptr, sizeof(RTreeNode)*tree_size);
        tree_node_file.close();

        // load the nodes of the search graph
        QueryGraph::_StrNode * graph_node_list_ptr = (QueryGraph::_StrNode*)(
            shared_memory_ptr + shared_layout_ptr->GetGraphNodeListOffset()
        );
        hsgr_input_stream.read(
            (char*) graph_node_list_ptr,
            shared_layout_ptr->graph_node_list_size*sizeof(QueryGraph::_StrNode)
        );

        // load the edges of the search graph
        QueryGraph::_StrEdge * graph_edge_list_ptr = (QueryGraph::_StrEdge *)(
            shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffsett()
        );
        hsgr_input_stream.read(
            (char*) graph_edge_list_ptr,
            shared_layout_ptr->graph_edge_list_size*sizeof(QueryGraph::_StrEdge)
        );
        hsgr_input_stream.close();

        //TODO swap load region and shared region1

        SimpleLogger().Write() << "all data loaded. pressing a key deallocates memory";
        std::cin.get();

    } catch(const std::exception & e) {
        SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/event.h"

#if defined(WEBRTC_WIN)
#include <windows.h>
#elif defined(WEBRTC_POSIX)
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#else
#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
#endif

#include "rtc_base/checks.h"

namespace rtc {

#if defined(WEBRTC_WIN)

Event::Event(bool manual_reset, bool initially_signaled) {
  event_handle_ = ::CreateEvent(nullptr,  // Security attributes.
                                manual_reset, initially_signaled,
                                nullptr);  // Name.
  RTC_CHECK(event_handle_);
}

Event::~Event() {
  CloseHandle(event_handle_);
}

void Event::Set() {
  SetEvent(event_handle_);
}

void Event::Reset() {
  ResetEvent(event_handle_);
}

bool Event::Wait(int milliseconds) {
  DWORD ms = (milliseconds == kForever) ? INFINITE : milliseconds;
  return (WaitForSingleObject(event_handle_, ms) == WAIT_OBJECT_0);
}

#elif defined(WEBRTC_POSIX)

Event::Event(bool manual_reset, bool initially_signaled)
    : is_manual_reset_(manual_reset),
      event_status_(initially_signaled) {
  RTC_CHECK(pthread_mutex_init(&event_mutex_, nullptr) == 0);
  RTC_CHECK(pthread_cond_init(&event_cond_, nullptr) == 0);
}

Event::~Event() {
  pthread_mutex_destroy(&event_mutex_);
  pthread_cond_destroy(&event_cond_);
}

void Event::Set() {
  pthread_mutex_lock(&event_mutex_);
  event_status_ = true;
  pthread_cond_broadcast(&event_cond_);
  pthread_mutex_unlock(&event_mutex_);
}

void Event::Reset() {
  pthread_mutex_lock(&event_mutex_);
  event_status_ = false;
  pthread_mutex_unlock(&event_mutex_);
}

bool Event::Wait(int milliseconds) {
  int error = 0;

  struct timespec ts;
  if (milliseconds != kForever) {
    // Converting from seconds and microseconds (1e-6) plus
    // milliseconds (1e-3) to seconds and nanoseconds (1e-9).

#ifdef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
    // Use relative time version, which tends to be more efficient for
    // pthread implementations where provided (like on Android).
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds % 1000) * 1000000;
#else
    struct timeval tv;
    gettimeofday(&tv, nullptr);

    ts.tv_sec = tv.tv_sec + (milliseconds / 1000);
    ts.tv_nsec = tv.tv_usec * 1000 + (milliseconds % 1000) * 1000000;

    // Handle overflow.
    if (ts.tv_nsec >= 1000000000) {
      ts.tv_sec++;
      ts.tv_nsec -= 1000000000;
    }
#endif
  }

  pthread_mutex_lock(&event_mutex_);
  if (milliseconds != kForever) {
    while (!event_status_ && error == 0) {
#ifdef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE
      error = pthread_cond_timedwait_relative_np(
          &event_cond_, &event_mutex_, &ts);
#else
      error = pthread_cond_timedwait(&event_cond_, &event_mutex_, &ts);
#endif
    }
  } else {
    while (!event_status_ && error == 0)
      error = pthread_cond_wait(&event_cond_, &event_mutex_);
  }

  // NOTE(liulk): Exactly one thread will auto-reset this event. All
  // the other threads will think it's unsignaled.  This seems to be
  // consistent with auto-reset events in WEBRTC_WIN
  if (error == 0 && !is_manual_reset_)
    event_status_ = false;

  pthread_mutex_unlock(&event_mutex_);

  return (error == 0);
}

#endif

}  // namespace rtc
<commit_msg>Delete use of pthread_cond_timedwait_relative_np.<commit_after>/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/event.h"

#if defined(WEBRTC_WIN)
#include <windows.h>
#elif defined(WEBRTC_POSIX)
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#else
#error "Must define either WEBRTC_WIN or WEBRTC_POSIX."
#endif

#include "rtc_base/checks.h"

namespace rtc {

#if defined(WEBRTC_WIN)

Event::Event(bool manual_reset, bool initially_signaled) {
  event_handle_ = ::CreateEvent(nullptr,  // Security attributes.
                                manual_reset, initially_signaled,
                                nullptr);  // Name.
  RTC_CHECK(event_handle_);
}

Event::~Event() {
  CloseHandle(event_handle_);
}

void Event::Set() {
  SetEvent(event_handle_);
}

void Event::Reset() {
  ResetEvent(event_handle_);
}

bool Event::Wait(int milliseconds) {
  DWORD ms = (milliseconds == kForever) ? INFINITE : milliseconds;
  return (WaitForSingleObject(event_handle_, ms) == WAIT_OBJECT_0);
}

#elif defined(WEBRTC_POSIX)

Event::Event(bool manual_reset, bool initially_signaled)
    : is_manual_reset_(manual_reset),
      event_status_(initially_signaled) {
  RTC_CHECK(pthread_mutex_init(&event_mutex_, nullptr) == 0);
  RTC_CHECK(pthread_cond_init(&event_cond_, nullptr) == 0);
}

Event::~Event() {
  pthread_mutex_destroy(&event_mutex_);
  pthread_cond_destroy(&event_cond_);
}

void Event::Set() {
  pthread_mutex_lock(&event_mutex_);
  event_status_ = true;
  pthread_cond_broadcast(&event_cond_);
  pthread_mutex_unlock(&event_mutex_);
}

void Event::Reset() {
  pthread_mutex_lock(&event_mutex_);
  event_status_ = false;
  pthread_mutex_unlock(&event_mutex_);
}

bool Event::Wait(int milliseconds) {
  int error = 0;

  struct timespec ts;
  if (milliseconds != kForever) {
    // Converting from seconds and microseconds (1e-6) plus
    // milliseconds (1e-3) to seconds and nanoseconds (1e-9).

    struct timeval tv;
    gettimeofday(&tv, nullptr);

    ts.tv_sec = tv.tv_sec + (milliseconds / 1000);
    ts.tv_nsec = tv.tv_usec * 1000 + (milliseconds % 1000) * 1000000;

    // Handle overflow.
    if (ts.tv_nsec >= 1000000000) {
      ts.tv_sec++;
      ts.tv_nsec -= 1000000000;
    }
  }

  pthread_mutex_lock(&event_mutex_);
  if (milliseconds != kForever) {
    while (!event_status_ && error == 0) {
      error = pthread_cond_timedwait(&event_cond_, &event_mutex_, &ts);
    }
  } else {
    while (!event_status_ && error == 0)
      error = pthread_cond_wait(&event_cond_, &event_mutex_);
  }

  // NOTE(liulk): Exactly one thread will auto-reset this event. All
  // the other threads will think it's unsignaled.  This seems to be
  // consistent with auto-reset events in WEBRTC_WIN
  if (error == 0 && !is_manual_reset_)
    event_status_ = false;

  pthread_mutex_unlock(&event_mutex_);

  return (error == 0);
}

#endif

}  // namespace rtc
<|endoftext|>