GeographicLib: Utility.hpp Source File (original) (raw)

36 private:

37 static bool gregorian(int y, int m, int d) {

38

39

40

41

42

43

44 return 100 * (100 * y + m) + d >= 17520914;

45 }

46 static bool gregorian(int s) {

47 return s >= 639799;

48 }

49 public:

50

51

52

53

54

55

56

57

58

59

60 static int day(int y, int m = 1, int d = 1);

61

62

63

64

65

66

67

68

69

70

71

72

73 static int day(int y, int m, int d, bool check);

74

75

76

77

78

79

80

81

82

83 static void date(int s, int& y, int& m, int& d);

84

85

86

87

88

89

90

91

92

93

94

95

96

97 static void date(const std::string& s, int& y, int& m, int& d);

98

99

100

101

102

103

104

105

106

107

108 static int dow(int y, int m, int d) { return dow(day(y, m, d)); }

109

110

111

112

113

114

115

116

117 static int dow(int s) {

118 return (s + 5) % 7;

119 }

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135 template static T fractionalyear(const std::string& s) {

136 try {

137 return val(s);

138 }

139 catch (const std::exception&) {}

140 int y, m, d;

141 date(s, y, m, d);

142 int t = day(y, m, d, true);

143 return T(y) + T(t - day(y)) / T(day(y + 1) - day(y));

144 }

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161 template static std::string str(T x, int p = -1) {

162 std::ostringstream s;

163 if (p >= 0) s << std::fixed << std::setprecision(p);

164 s << std::boolalpha << x; return s.str();

165 }

166

167

168

169

170

171

172

173 static std::string trim(const std::string& s);

174

175

176

177

178

179

180

181

182

183

184

185

186 static int lookup(const std::string& s, char c);

187

188

189

190

191

192

193

194

195

196

197

198

199 static int lookup(const char* s, char c);

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225 template static T val(const std::string& s) {

226

227

228 T x;

229 std::string errmsg, t(trim(s));

230 do {

231 std::istringstream is(t);

232 if (!(is >> x)) {

233 errmsg = "Cannot decode " + t;

234 break;

235 }

236 int pos = int(is.tellg());

237 if (!(pos < 0 || pos == int(t.size()))) {

238 errmsg = "Extra text " + t.substr(pos) + " at end of " + t;

239 break;

240 }

241 return x;

242 } while (false);

243 x = std::numeric_limits::is_integer ? 0 : nummatch(t);

244 if (x == 0)

246 return x;

247 }

248

249

250

251

252

253

254

255

256

257

258

259

260 template static T nummatch(const std::string& s) {

261 if (s.length() < 3)

262 return 0;

263 std::string t(s);

264 for (std:🧵:iterator p = t.begin(); p != t.end(); ++p)

265 *p = char(std::toupper(*p));

266 for (size_t i = s.length(); i--;)

267 t[i] = char(std::toupper(s[i]));

268 int sign = t[0] == '-' ? -1 : 1;

269 std:🧵:size_type p0 = t[0] == '-' || t[0] == '+' ? 1 : 0;

270 std:🧵:size_type p1 = t.find_last_not_of('0');

271 if (p1 == std:🧵:npos || p1 + 1 < p0 + 3)

272 return 0;

273

274 t = t.substr(p0, p1 + 1 - p0);

275 if (t == "NAN" || t == "1.#QNAN" || t == "1.#SNAN" || t == "1.#IND" ||

276 t == "1.#R")

277 return Math::NaN();

278 else if (t == "INF" || t == "1.#INF" || t == "INFINITY")

279 return sign * Math::infinity();

280 return 0;

281 }

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298 template static T fract(const std::string& s) {

299 std:🧵:size_type delim = s.find('/');

300 return

301 !(delim != std:🧵:npos && delim >= 1 && delim + 2 <= s.size()) ?

302 val(s) :

303

304 val(s.substr(0, delim)) / val(s.substr(delim + 1));

305 }

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320 template<typename ExtT, typename IntT, bool bigendp>

321 static void readarray(std::istream& str, IntT array[], size_t num) {

322#if GEOGRAPHICLIB_PRECISION < 4

323

324 if (sizeof(IntT) == sizeof(ExtT) &&

325 std::numeric_limits::is_integer ==

326 std::numeric_limits::is_integer)

327 {

328

329 str.read(reinterpret_cast<char*>(array), num * sizeof(ExtT));

330 if (!str.good())

332

333 if (bigendp != Math::bigendian) {

334 for (size_t i = num; i--;)

335 array[i] = Math::swab(array[i]);

336 }

337 }

338 else

339#endif

340 {

341 const int bufsize = 1024;

342 ExtT buffer[bufsize];

343 int k = int(num);

344 int i = 0;

345 while (k) {

346 int n = (std::min)(k, bufsize);

347 str.read(reinterpret_cast<char*>(buffer), n * sizeof(ExtT));

348 if (!str.good())

350 for (int j = 0; j < n; ++j) {

351

352 ExtT x = bigendp == Math::bigendian ? buffer[j] :

353 Math::swab(buffer[j]);

354#if GEOGRAPHICLIB_PRECISION > 2

355

356 if (typeid(ExtT) == typeid(double) &&

357 typeid(IntT) == typeid(Math::real)) {

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399 std::ostringstream str;

400 str << std::scientific

401 << std::setprecision(std::numeric_limits::digits10-1)

402 << x;

403 if (val(str.str()) == x)

404 array[i++] = val(str.str());

405 else

406 array[i++] = IntT(x);

407 } else {

408

409

410 array[i++] = IntT(x);

411 }

412#else

413

414 array[i++] = IntT(x);

415#endif

416 }

417 k -= n;

418 }

419 }

420 return;

421 }

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436 template<typename ExtT, typename IntT, bool bigendp>

437 static void readarray(std::istream& str, std::vector& array) {

438 if (array.size() > 0)

439 readarray<ExtT, IntT, bigendp>(str, &array[0], array.size());

440 }

441

442

443

444

445

446

447

448

449

450

451

452

453

454 template<typename ExtT, typename IntT, bool bigendp>

455 static void writearray(std::ostream& str, const IntT array[], size_t num)

456 {

457#if GEOGRAPHICLIB_PRECISION < 4

458 if (sizeof(IntT) == sizeof(ExtT) &&

459 std::numeric_limits::is_integer ==

460 std::numeric_limits::is_integer &&

461 bigendp == Math::bigendian)

462 {

463

464 str.write(reinterpret_cast<const char*>(array), num * sizeof(ExtT));

465 if (!str.good())

467 }

468 else

469#endif

470 {

471 const int bufsize = 1024;

472 ExtT buffer[bufsize];

473 int k = int(num);

474 int i = 0;

475 while (k) {

476 int n = (std::min)(k, bufsize);

477 for (int j = 0; j < n; ++j)

478

479 buffer[j] = bigendp == Math::bigendian ? ExtT(array[i++]) :

480 Math::swab(ExtT(array[i++]));

481 str.write(reinterpret_cast<const char*>(buffer), n * sizeof(ExtT));

482 if (!str.good())

484 k -= n;

485 }

486 }

487 return;

488 }

489

490

491

492

493

494

495

496

497

498

499

500

501 template<typename ExtT, typename IntT, bool bigendp>

502 static void writearray(std::ostream& str, std::vector& array) {

503 if (array.size() > 0)

504 writearray<ExtT, IntT, bigendp>(str, &array[0], array.size());

505 }

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529 static bool ParseLine(const std::string& line,

530 std::string& key, std::string& value,

531 char equals = '\0', char comment = '#');

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552 static int set_digits(int ndigits = 0);

553

554 };

563 template<> inline std::string Utility::valstd::string(const std::string& s)

564 { return trim(s); }

580 template<> inline bool Utility::val(const std::string& s) {

581 std::string t(trim(s));

582 if (t.empty()) return false;

583 bool x;

584 {

585 std::istringstream is(t);

586 if (is >> x) {

587 int pos = int(is.tellg());

588 if (!(pos < 0 || pos == int(t.size())))

589 throw GeographicErr("Extra text " + t.substr(pos) +

590 " at end of " + t);

591 return x;

592 }

593 }

594 for (std:🧵:iterator p = t.begin(); p != t.end(); ++p)

595 *p = char(std::tolower(*p));

596 switch (t[0]) {

597 case 'f':

598 if (t == "f" || t == "false") return false;

599 break;

600 case 'n':

601 if (t == "n" || t == "nil" || t == "no") return false;

602 break;

603 case 'o':

604 if (t == "off") return false;

605 else if (t == "on") return true;

606 break;

607 case 't':

608 if (t == "t" || t == "true") return true;

609 break;

610 case 'y':

611 if (t == "y" || t == "yes") return true;

612 break;

613 default:

614 break;

615 }

616 throw GeographicErr("Cannot decode " + t + " as a bool");

617 }

631 template<> inline std::string Utility::strMath::real(Math::real x, int p) {

632 using std::isfinite;

633 if (!isfinite(x))

634 return x < 0 ? std::string("-inf") :

635 (x > 0 ? std::string("inf") : std::string("nan"));

636 std::ostringstream s;

637 if (p >= 0) s << std::fixed << std::setprecision(p);

638 s << x; return s.str();

639 }