From: Otto Moerbeek Date: Tue, 25 Feb 2025 16:19:10 +0000 (+0100) Subject: Compute LOC text representation without using floating point for latitude and longitude X-Git-Tag: dnsdist-2.0.0-beta1~22^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=686eb86f06918ff067d8186b606146678a873e32;p=thirdparty%2Fpdns.git Compute LOC text representation without using floating point for latitude and longitude Signed-off-by: Otto Moerbeek --- diff --git a/pdns/sillyrecords.cc b/pdns/sillyrecords.cc index a6edc189e2..af935f3d5a 100644 --- a/pdns/sillyrecords.cc +++ b/pdns/sillyrecords.cc @@ -301,8 +301,6 @@ string LOCRecordContent::getZoneRepresentation(bool /* noDot */) const // convert d_version, d_size, d_horiz/vertpre, d_latitude, d_longitude, d_altitude to: // 51 59 00.000 N 5 55 00.000 E 4.00m 1.00m 10000.00m 10.00m - double latitude= ((int32_t)((uint32_t)d_latitude - ((uint32_t)1<<31)))/3600000.0; - double longitude=((int32_t)((uint32_t)d_longitude - ((uint32_t)1<<31)))/3600000.0; double altitude= ((int32_t)d_altitude )/100.0 - 100000; double size=0.01*((d_size>>4)&0xf); @@ -320,15 +318,43 @@ string LOCRecordContent::getZoneRepresentation(bool /* noDot */) const while(count--) vertpre*=10; - double remlat=60.0*(latitude-(int)latitude); - double remlong=60.0*(longitude-(int)longitude); - static const boost::format fmt("%d %d %2.03f %c %d %d %2.03f %c %.2fm %.2fm %.2fm %.2fm"); + char hemLat = 'N'; + uint32_t lat = d_latitude; + if (lat >= 1U << 31) { + lat -= 1U << 31; + } + else { + hemLat = 'S'; + lat = (1U << 31) - lat; + } + auto fracLat = lat % 1000; + lat /= 1000; + auto secLat = lat % 60; + lat /= 60; + auto minutesLat = lat % 60; + auto degreesLat = lat / 60; + + char hemLon= 'E'; + uint32_t lon = d_longitude; + if (lon >= 1U << 31) { + lon -= 1U << 31; + } + else { + hemLon = 'W'; + lon = (1U << 31) - lon; + } + auto fracLon = lon % 1000; + lon /= 1000; + auto secLon = lon % 60; + lon /= 60; + auto minutesLon = lon % 60; + auto degreesLon = lon / 60; + + static const boost::format fmt("%d %d %d.%03d %c %d %d %d.%03d %c %.2fm %.2fm %.2fm %.2fm"); std::string ret = boost::str( boost::format(fmt) - % abs((int)latitude) % abs((int) ((latitude-(int)latitude)*60)) - % fabs((double)((remlat-(int)remlat)*60.0)) % (latitude>0 ? 'N' : 'S') - % abs((int)longitude) % abs((int) ((longitude-(int)longitude)*60)) - % fabs((double)((remlong-(int)remlong)*60.0)) % (longitude>0 ? 'E' : 'W') + % degreesLat % minutesLat % secLat % fracLat % hemLat + % degreesLon % minutesLon % secLon % fracLon % hemLon % altitude % size % horizpre % vertpre ); diff --git a/pdns/test-dnsrecords_cc.cc b/pdns/test-dnsrecords_cc.cc index fb83a86bbc..bbe1761556 100644 --- a/pdns/test-dnsrecords_cc.cc +++ b/pdns/test-dnsrecords_cc.cc @@ -117,7 +117,13 @@ BOOST_AUTO_TEST_CASE(test_record_types) { (CASE_L(QType::LOC, "32 7 19 S 116 2 25 E 10m", "32 7 19.000 S 116 2 25.000 E 10.00m 1.00m 10000.00m 10.00m", "\x00\x12\x16\x13\x79\x1b\x7d\x28\x98\xe6\x48\x68\x00\x98\x9a\x68")) (CASE_L(QType::LOC, "42 21 54 N 71 06 18 W -24m 30m", "42 21 54.000 N 71 6 18.000 W -24.00m 30.00m 10000.00m 10.00m", "\x00\x33\x16\x13\x89\x17\x2d\xd0\x70\xbe\x15\xf0\x00\x98\x8d\x20")) (CASE_L(QType::LOC, "42 21 43.952 N 71 5 6.344 W -24m 1m 200m", "42 21 43.952 N 71 5 6.344 W -24.00m 1.00m 200.00m 10.00m", "\x00\x12\x24\x13\x89\x17\x06\x90\x70\xbf\x2d\xd8\x00\x98\x8d\x20")) + (CASE_L(QType::LOC, "57 9 0.000 N 2 7 9.998 W 0.00m 0.00m 0.00m 0.00m", "57 9 0.000 N 2 7 9.998 W 0.00m 0.00m 0.00m 0.00m", "\x00\x00\x00\x00\x8c\x43\x57\xe0\x7f\x8b\x93\x52\x00\x98\x96\x80")) + (CASE_L(QType::LOC, "57 8 59.999 N 2 7 9.998 W 0.00m 0.00m 0.00m 0.00m", "57 8 59.999 N 2 7 9.998 W 0.00m 0.00m 0.00m 0.00m", "\x00\x00\x00\x00\x8c\x43\x57\xdf\x7f\x8b\x93\x52\x00\x98\x96\x80")) // local name + (CASE_L(QType::LOC, "51 11 60.000 N 2 12 5.080 W 0.00m 0.00m 0.00m 0.00m", "51 12 0.000 N 2 12 5.080 W 0.00m 0.00m 0.00m 0.00m", "\x00\x00\x00\x00\x8a\xfc\x80\x00\x7f\x87\x12\xa8\x00\x98\x96\x80")) + (CASE_L(QType::LOC, "51 11 59.999 N 2 12 5.080 W 0.00m 0.00m 0.00m 0.00m", "51 11 59.999 N 2 12 5.080 W 0.00m 0.00m 0.00m 0.00m", "\x00\x00\x00\x00\x8a\xfc\x7f\xff\x7f\x87\x12\xa8\x00\x98\x96\x80")) + (CASE_L(QType::LOC, "49 18 0.000 N 10 35 0.000 E 409.00m 1.00m 10000.00m 10.00m", "49 18 0.000 N 10 35 0.000 E 409.00m 1.00m 10000.00m 10.00m", "\x00\x12\x16\x13\x8a\x94\x21\x40\x82\x45\x5c\x20\x00\x99\x36\x44")) + (CASE_L(QType::LOC, "49 18 0.000 S 10 35 0.000 W 409.00m 1.00m 10000.00m 10.00m", "49 18 0.000 S 10 35 0.000 W 409.00m 1.00m 10000.00m 10.00m", "\x00\x12\x16\x13\x75\x6b\xde\xc0\x7d\xba\xa3\xe0\x00\x99\x36\x44")) (CASE_S(QType::SRV, "10 10 5060 sip.rec.test.", "\x00\x0a\x00\x0a\x13\xc4\x03sip\x03rec\x04test\x00")) // non-local name (CASE_S(QType::SRV, "10 10 5060 sip.example.com.", "\x00\x0a\x00\x0a\x13\xc4\x03sip\x07""example\x03""com\x00"))