Permalink
Browse files

LOC is now parsed (but wire format is still wrong, I think).

  • Loading branch information...
1 parent 193800f commit e9cf6b15deda7d3f0cb5e1de54bb29ee22dd8f2b @tobez committed Apr 29, 2011
Showing with 173 additions and 4 deletions.
  1. +125 −4 loc.c
  2. +47 −0 textparse.c
  3. +1 −0 textparse.h
View
@@ -19,21 +19,47 @@
#include "carp.h"
#include "rr.h"
+static uint8_t double2loc_format(double val)
+{
+ if (val > 1000000000) {
+ return (((uint8_t)(val / 1000000000)) << 4) | 9;
+ } else if (val > 100000000) {
+ return (((uint8_t)(val / 100000000)) << 4) | 8;
+ } else if (val > 10000000) {
+ return (((uint8_t)(val / 10000000)) << 4) | 7;
+ } else if (val > 1000000) {
+ return (((uint8_t)(val / 1000000)) << 4) | 6;
+ } else if (val > 100000) {
+ return (((uint8_t)(val / 100000)) << 4) | 5;
+ } else if (val > 10000) {
+ return (((uint8_t)(val / 10000)) << 4) | 4;
+ } else if (val > 1000) {
+ return (((uint8_t)(val / 1000)) << 4) | 3;
+ } else if (val > 100) {
+ return (((uint8_t)(val / 100)) << 4) | 2;
+ } else if (val > 10) {
+ return (((uint8_t)(val / 10)) << 4) | 1;
+ } else {
+ return (((uint8_t)(val)) << 4);
+ }
+
+}
+
static struct rr *loc_parse(char *name, long ttl, int type, char *s)
{
struct rr_loc *rr = getmem(sizeof(*rr));
long long i;
int deg;
int min;
- double sec;
+ double sec, val;
+ /* latitude block */
i = extract_integer(&s, "degrees latitude");
if (i < 0)
return NULL;
if (i > 90)
return bitch("degrees latitude not in the range 0..90");
deg = i;
-
min = 0;
sec = 0;
if (isdigit(*s)) {
@@ -42,10 +68,105 @@ static struct rr *loc_parse(char *name, long ttl, int type, char *s)
return NULL;
if (i > 59)
return bitch("minutes latitude not in the range 0..59");
- deg = i;
+ min = i;
+
+ if (isdigit(*s)) { /* restricted floating point, starting with a digit */
+ if (extract_double(&s, "seconds latitude", &sec, 0) < 0)
+ return NULL;
+ if (sec < 0 || sec > 59.999)
+ return bitch("seconds latitude not in the range 0..59.999");
+ }
+ }
+ rr->latitude = sec*1000 + .5 + min*1000*60 + deg*1000*60*60;
+ if (*s == 'n' || *s == 'N') {
+ s++;
+ rr->latitude = 2147483648u + rr->latitude;
+ } else if (*s == 's' || *s == 'S') {
+ s++;
+ rr->latitude = 2147483648u - rr->latitude;
+ } else {
+ return bitch("latitude: N or S is expected");
+ }
+ if (*s && !isspace(*s) && *s != ';' && *s != ')') {
+ return bitch("latitude: N or S is expected");
+ }
+ s = skip_white_space(s);
+ if (!s) return NULL;
+
+ /* longitude block */
+ i = extract_integer(&s, "degrees longitude");
+ if (i < 0)
+ return NULL;
+ if (i > 180)
+ return bitch("degrees longitude not in the range 0..90");
+ deg = i;
+ min = 0;
+ sec = 0;
+ if (isdigit(*s)) {
+ i = extract_integer(&s, "minutes longitude");
+ if (i < 0)
+ return NULL;
+ if (i > 59)
+ return bitch("minutes longitude not in the range 0..59");
+ min = i;
+
+ if (isdigit(*s)) { /* restricted floating point, starting with a digit */
+ if (extract_double(&s, "seconds longitude", &sec, 0) < 0)
+ return NULL;
+ if (sec < 0 || sec > 59.999)
+ return bitch("seconds longitude not in the range 0..59.999");
+ }
+ }
+ rr->longitude = sec*1000 + .5 + min*1000*60 + deg*1000*60*60;
+ if (*s == 'e' || *s == 'E') {
+ s++;
+ rr->longitude = 2147483648u + rr->longitude;
+ } else if (*s == 'w' || *s == 'W') {
+ s++;
+ rr->longitude = 2147483648u - rr->latitude;
+ } else {
+ return bitch("longitude: E or W is expected");
+ }
+ if (*s && !isspace(*s) && *s != ';' && *s != ')') {
+ return bitch("longitude: E or W is expected");
+ }
+ s = skip_white_space(s);
+ if (!s) return NULL;
+
+ if (extract_double(&s, "altitude", &val, 1) < 0)
+ return NULL;
+ if (val < -100000.00 || val > 42849672.95)
+ return bitch("altitude is out of supported range");
+ rr->altitude = (val + 100000.00) * 100 + 0.5;
+
+ if (*s) {
+ if (extract_double(&s, "sphere size", &val, 1) < 0)
+ return NULL;
+ if (val < 0 || val > 90000000.00)
+ return bitch("sphere size is out of supported range");
+ rr->size = double2loc_format(val * 100 + 0.5);
+
+ if (*s) {
+ if (extract_double(&s, "horizontal precision", &val, 1) < 0)
+ return NULL;
+ if (val < 0 || val > 90000000.00)
+ return bitch("horizontal precision is out of supported range");
+ rr->horiz_pre = double2loc_format(val * 100 + 0.5);
- if (isdigit(*s)) {
+ if (*s) {
+ if (extract_double(&s, "vertical precision", &val, 1) < 0)
+ return NULL;
+ if (val < 0 || val > 90000000.00)
+ return bitch("vertical precision is out of supported range");
+ rr->vert_pre = double2loc_format(val * 100 + 0.5);
+ } else {
+ rr->vert_pre = double2loc_format(10 * 100 + 0.5);
+ }
+ } else {
+ rr->horiz_pre = double2loc_format(10000 * 100 + 0.5);
}
+ } else {
+ rr->size = double2loc_format(1 * 100 + 0.5);
}
if (*s) {
View
@@ -307,6 +307,53 @@ long long extract_integer(char **input, char *what)
return r;
}
+int extract_double(char **input, char *what, double *val, int skip_m)
+{
+ char *s = *input;
+ char *end = NULL;
+ char *stop;
+ char c;
+ int saw_m = 0;
+
+ while (isdigit(*s) || *s == '+' || *s == '-' || *s == '.')
+ s++;
+ if (*s && !isspace(*s) && *s != ';' && *s != ')') {
+ if (skip_m && (*s == 'm' || *s == 'M')) {
+ saw_m = 1;
+ } else {
+ bitch("%s is not valid", what);
+ return -1;
+ }
+ }
+ if (!*s) end = s;
+ c = *s;
+ *s = '\0';
+ *val = strtod(*input, &stop);
+ if (*stop != '\0') {
+ *s = c;
+ bitch("%s is not valid", what);
+ return -1;
+ }
+ *s = c;
+
+ if (saw_m) {
+ s++;
+ if (*s && !isspace(*s) && *s != ';' && *s != ')') {
+ bitch("%s is not valid", what);
+ return -1;
+ }
+ }
+
+ if (end) {
+ *input = end;
+ } else {
+ *input = skip_white_space(s);
+ if (!*input)
+ return -1; /* bitching's done elsewhere */
+ }
+ return 1;
+}
+
long extract_timevalue(char **input, char *what)
{
char *s = *input;
View
@@ -39,6 +39,7 @@ long extract_timevalue(char **input, char *what);
long long extract_timestamp(char **input, char *what);
int extract_ipv4(char **input, char *what, struct in_addr *addr);
int extract_ipv6(char **input, char *what, struct in6_addr *addr);
+int extract_double(char **input, char *what, double *val, int skip_m);
struct binary_data extract_base32hex_binary_data(char **input, char *what);
struct binary_data extract_base64_binary_data(char **input, char *what);
struct binary_data extract_text(char **input, char *what);

0 comments on commit e9cf6b1

Please sign in to comment.