10 #if !defined(GEOGRAPHICLIB_UTILITY_HPP)
11 #define GEOGRAPHICLIB_UTILITY_HPP 1
21 # pragma warning (push)
22 # pragma warning (disable: 4127)
25 namespace GeographicLib {
35 static bool gregorian(
int y,
int m,
int d) {
42 return 100 * (100 * y + m) + d >= 17520914;
44 static bool gregorian(
int s) {
58 static int day(
int y,
int m = 1,
int d = 1) throw() {
94 bool greg = gregorian(y, m, d);
95 y += (m + 9) / 12 - 1;
103 + (greg ? (y / 100) / 4 - (y / 100) + 2 : 0)
121 static int day(
int y,
int m,
int d,
bool check) {
122 int s = day(y, m, d);
127 if (!(s > 0 && y == y1 && m == m1 && d == d1))
129 str(y) +
"-" + str(m) +
"-" + str(d)
130 + (s > 0 ?
"; use " +
131 str(y1) +
"-" + str(m1) +
"-" + str(d1) :
132 " before 0001-01-01"));
144 static void date(
int s,
int& y,
int& m,
int& d)
throw() {
146 bool greg = gregorian(s);
152 c = (4 * s + 3) / 146097;
153 s -= (c * 146097) / 4;
155 y = (4 * s + 3) / 1461;
158 m = (5 * s + 2) / 153;
159 s -= (153 * m + 2) / 5;
162 m = (m + 2) % 12 + 1;
176 static void date(
const std::string& s,
int& y,
int& m,
int& d) {
177 int y1, m1 = 1, d1 = 1;
178 const char* digits =
"0123456789";
179 std::string::size_type p1 = s.find_first_not_of(digits);
180 if (p1 == std::string::npos)
182 else if (s[p1] !=
'-')
187 y1 = num<int>(s.substr(0, p1));
188 if (++p1 == s.size())
190 std::string::size_type p2 = s.find_first_not_of(digits, p1);
191 if (p2 == std::string::npos)
192 m1 = num<int>(s.substr(p1));
193 else if (s[p2] !=
'-')
198 m1 = num<int>(s.substr(p1, p2 - p1));
199 if (++p2 == s.size())
201 d1 = num<int>(s.substr(p2));
204 y = y1; m = m1; d = d1;
216 static int dow(
int y,
int m,
int d)
throw() {
return dow(day(y, m, d)); }
225 static int dow(
int s)
throw() {
246 catch (
const std::exception&) {
250 int t = day(y, m, d,
true);
251 return T(y) + T(t - day(y)) / T(day(y + 1) - day(y));
266 template<
typename T>
static std::string
str(T x,
int p = -1) {
267 if (!std::numeric_limits<T>::is_integer && !Math::isfinite<T>(x))
268 return x < 0 ? std::string(
"-inf") :
269 (x > 0 ? std::string(
"inf") : std::string(
"nan"));
270 std::ostringstream s;
271 if (p >= 0) s << std::fixed << std::setprecision(p);
272 s << x;
return s.str();
283 template<
typename T>
static T
num(
const std::string& s) {
287 std::istringstream is(s);
289 errmsg =
"Cannot decode " + s;
292 int pos = int(is.tellg());
293 if (!(pos < 0 || pos ==
int(s.size()))) {
294 errmsg =
"Extra text " + s.substr(pos) +
" at end of " + s;
299 x = std::numeric_limits<T>::is_integer ? 0 : nummatch<T>(s);
313 template<
typename T>
static T
nummatch(
const std::string& s) {
317 t.resize(s.length());
318 std::transform(s.begin(), s.end(), t.begin(), (int(*)(int))std::toupper);
319 for (
size_t i = s.length(); i--;)
320 t[i] =
char(std::toupper(s[i]));
321 int sign = t[0] ==
'-' ? -1 : 1;
322 std::string::size_type p0 = t[0] ==
'-' || t[0] ==
'+' ? 1 : 0;
323 std::string::size_type p1 = t.find_last_not_of(
'0');
324 if (p1 == std::string::npos || p1 + 1 < p0 + 3)
327 t = t.substr(p0, p1 + 1 - p0);
328 if (t ==
"NAN" || t ==
"1.#QNAN" || t ==
"1.#SNAN" || t ==
"1.#IND" ||
330 return Math::NaN<T>();
331 else if (t ==
"INF" || t ==
"1.#INF")
332 return sign * Math::infinity<T>();
344 template<
typename T>
static T
fract(
const std::string& s) {
345 std::string::size_type delim = s.find(
'/');
347 !(delim != std::string::npos && delim >= 1 && delim + 2 <= s.size()) ?
350 num<T>(s.substr(0, delim)) / num<T>(s.substr(delim + 1));
364 static int lookup(
const std::string& s,
char c)
throw() {
365 std::string::size_type r = s.find(
char(toupper(c)));
366 return r == std::string::npos ? -1 : int(r);
382 template<
typename ExtT,
typename IntT,
bool bigendp>
384 IntT array[],
size_t num) {
385 if (
sizeof(IntT) ==
sizeof(ExtT) &&
386 std::numeric_limits<IntT>::is_integer ==
387 std::numeric_limits<ExtT>::is_integer) {
389 str.read(reinterpret_cast<char *>(array), num *
sizeof(ExtT));
393 for (
size_t i = num; i--;)
394 array[i] = Math::swab<IntT>(array[i]);
397 const int bufsize = 1024;
398 ExtT buffer[bufsize];
402 int n = (std::min)(k, bufsize);
403 str.read(reinterpret_cast<char *>(buffer), n *
sizeof(ExtT));
406 for (
int j = 0; j < n; ++j)
409 Math::swab<ExtT>(buffer[j]));
429 template<
typename ExtT,
typename IntT,
bool bigendp>
431 std::vector<IntT>& array) {
432 readarray<ExtT, IntT, bigendp>(str, &array[0], array.size());
447 template<
typename ExtT,
typename IntT,
bool bigendp>
449 const IntT array[],
size_t num) {
450 if (
sizeof(IntT) ==
sizeof(ExtT) &&
451 std::numeric_limits<IntT>::is_integer ==
452 std::numeric_limits<ExtT>::is_integer &&
455 str.write(reinterpret_cast<const char *>(array), num *
sizeof(ExtT));
459 const int bufsize = 1024;
460 ExtT buffer[bufsize];
464 int n = (std::min)(k, bufsize);
465 for (
int j = 0; j < n; ++j)
468 Math::swab<ExtT>(ExtT(array[i++]));
469 str.write(reinterpret_cast<const char *>(buffer), n *
sizeof(ExtT));
489 template<
typename ExtT,
typename IntT,
bool bigendp>
491 std::vector<IntT>& array) {
492 writearray<ExtT, IntT, bigendp>(str, &array[0], array.size());
510 static bool ParseLine(
const std::string& line,
511 std::string& key, std::string& val);
517 #if defined(_MSC_VER)
518 # pragma warning (pop)
521 #endif // GEOGRAPHICLIB_UTILITY_HPP
static T fract(const std::string &s)
static int day(int y, int m, int d, bool check)
#define GEOGRAPHICLIB_EXPORT
static void readarray(std::istream &str, std::vector< IntT > &array)
static void readarray(std::istream &str, IntT array[], size_t num)
Some utility routines for GeographicLib.
static void date(const std::string &s, int &y, int &m, int &d)
static T fractionalyear(const std::string &s)
static void writearray(std::ostream &str, std::vector< IntT > &array)
static T nummatch(const std::string &s)
static void writearray(std::ostream &str, const IntT array[], size_t num)
static void date(int s, int &y, int &m, int &d)
static std::string str(T x, int p=-1)
static int dow(int y, int m, int d)
static const bool bigendian
static T num(const std::string &s)
Exception handling for GeographicLib.
Header for GeographicLib::Constants class.
static int lookup(const std::string &s, char c)
static int day(int y, int m=1, int d=1)