"Initial commit to Gerrit"
[profile/ivi/gpsd.git] / ais_json.c
1 /****************************************************************************
2
3 NAME
4    ais_json.c - deserialize AIS JSON
5
6 DESCRIPTION
7    This module uses the generic JSON parser to get data from AIS
8 representations to libgps structures.
9
10 ***************************************************************************/
11
12 #include <math.h>
13 #include <assert.h>
14 #include <string.h>
15 #include <stddef.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18
19 #include "gpsd.h"
20 #include "gps_json.h"
21
22 /*@ -mustdefine @*/
23 static void lenhex_unpack(const char *from,
24                           size_t * plen, /*@out@*/ char *to, size_t maxlen)
25 {
26     char *colon = strchr(from, ':');
27
28     *plen = (size_t) atoi(from);
29     if (colon != NULL)
30         (void)gpsd_hexpack(colon + 1, to, maxlen);
31 }
32
33 /*@ +mustdefine @*/
34
35 int json_ais_read(const char *buf,
36                   char *path, size_t pathlen, struct ais_t *ais,
37                   /*@null@*/ const char **endptr)
38 {
39     /* collected but not actually used yet */
40     bool scaled;
41     /*@-compdef@*//* splint is confused by storage declared in the .i file */
42     /*@-nullstate@*/
43
44 #define AIS_HEADER \
45         {"class",          t_check,    .dflt.check = "AIS"}, \
46         {"type",           t_uinteger, .addr.uinteger = &ais->type}, \
47         {"device",         t_string,   .addr.string = path, \
48                                           .len = pathlen}, \
49         {"repeat",         t_uinteger, .addr.uinteger = &ais->repeat}, \
50         {"scaled",         t_boolean,  .addr.boolean = &scaled, \
51                                           .dflt.boolean = false}, \
52         {"mmsi",           t_uinteger, .addr.uinteger = &ais->mmsi}
53
54     int status;
55
56 #include "ais_json.i"           /* JSON parser template structures */
57
58 #undef AIS_HEADER
59
60     memset(ais, '\0', sizeof(struct ais_t));
61
62     if (strstr(buf, "\"type\":1,") != NULL
63         || strstr(buf, "\"type\":2,") != NULL
64         || strstr(buf, "\"type\":3,") != NULL) {
65         status = json_read_object(buf, json_ais1, endptr);
66     } else if (strstr(buf, "\"type\":4,") != NULL
67                || strstr(buf, "\"type\":11,") != NULL) {
68         status = json_read_object(buf, json_ais4, endptr);
69         if (status == 0) {
70             ais->type4.year = AIS_YEAR_NOT_AVAILABLE;
71             ais->type4.month = AIS_MONTH_NOT_AVAILABLE;
72             ais->type4.day = AIS_DAY_NOT_AVAILABLE;
73             ais->type4.hour = AIS_HOUR_NOT_AVAILABLE;
74             ais->type4.minute = AIS_MINUTE_NOT_AVAILABLE;
75             ais->type4.second = AIS_SECOND_NOT_AVAILABLE;
76             (void)sscanf(timestamp, "%4u-%02u-%02uT%02u:%02u:%02uZ",
77                          &ais->type4.year,
78                          &ais->type4.month,
79                          &ais->type4.day,
80                          &ais->type4.hour,
81                          &ais->type4.minute, &ais->type4.second);
82         }
83     } else if (strstr(buf, "\"type\":5,") != NULL) {
84         status = json_read_object(buf, json_ais5, endptr);
85         if (status == 0) {
86             ais->type5.month = AIS_MONTH_NOT_AVAILABLE;
87             ais->type5.day = AIS_DAY_NOT_AVAILABLE;
88             ais->type5.hour = AIS_HOUR_NOT_AVAILABLE;
89             ais->type5.minute = AIS_MINUTE_NOT_AVAILABLE;
90             (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
91                          &ais->type5.month,
92                          &ais->type5.day,
93                          &ais->type5.hour, &ais->type5.minute);
94         }
95     } else if (strstr(buf, "\"type\":6,") != NULL) {
96         status = json_read_object(buf, json_ais6, endptr);
97         if (status == 0)
98             lenhex_unpack(data, &ais->type6.bitcount,
99                           ais->type6.bitdata, sizeof(ais->type6.bitdata));
100     } else if (strstr(buf, "\"type\":7,") != NULL
101                || strstr(buf, "\"type\":13,") != NULL) {
102         status = json_read_object(buf, json_ais7, endptr);
103     } else if (strstr(buf, "\"type\":8,") != NULL) {
104         status = json_read_object(buf, json_ais8, endptr);
105         if (status == 0)
106             lenhex_unpack(data, &ais->type8.bitcount,
107                           ais->type8.bitdata, sizeof(ais->type8.bitdata));
108     } else if (strstr(buf, "\"type\":9,") != NULL) {
109         status = json_read_object(buf, json_ais9, endptr);
110     } else if (strstr(buf, "\"type\":10,") != NULL) {
111         status = json_read_object(buf, json_ais10, endptr);
112     } else if (strstr(buf, "\"type\":12,") != NULL) {
113         status = json_read_object(buf, json_ais12, endptr);
114     } else if (strstr(buf, "\"type\":14,") != NULL) {
115         status = json_read_object(buf, json_ais14, endptr);
116     } else if (strstr(buf, "\"type\":15,") != NULL) {
117         status = json_read_object(buf, json_ais15, endptr);
118     } else if (strstr(buf, "\"type\":16,") != NULL) {
119         status = json_read_object(buf, json_ais16, endptr);
120     } else if (strstr(buf, "\"type\":17,") != NULL) {
121         status = json_read_object(buf, json_ais17, endptr);
122         if (status == 0)
123             lenhex_unpack(data, &ais->type17.bitcount,
124                           ais->type17.bitdata, sizeof(ais->type17.bitdata));
125     } else if (strstr(buf, "\"type\":18,") != NULL) {
126         status = json_read_object(buf, json_ais18, endptr);
127     } else if (strstr(buf, "\"type\":18,") != NULL) {
128         status = json_read_object(buf, json_ais17, endptr);
129     } else if (strstr(buf, "\"type\":19,") != NULL) {
130         status = json_read_object(buf, json_ais19, endptr);
131     } else if (strstr(buf, "\"type\":20,") != NULL) {
132         status = json_read_object(buf, json_ais20, endptr);
133     } else if (strstr(buf, "\"type\":21,") != NULL) {
134         status = json_read_object(buf, json_ais21, endptr);
135     } else if (strstr(buf, "\"type\":22,") != NULL) {
136         status = json_read_object(buf, json_ais22, endptr);
137     } else if (strstr(buf, "\"type\":23,") != NULL) {
138         status = json_read_object(buf, json_ais23, endptr);
139     } else if (strstr(buf, "\"type\":24,") != NULL) {
140         status = json_read_object(buf, json_ais24, endptr);
141     } else if (strstr(buf, "\"type\":25,") != NULL) {
142         status = json_read_object(buf, json_ais25, endptr);
143     } else if (strstr(buf, "\"type\":26,") != NULL) {
144         status = json_read_object(buf, json_ais26, endptr);
145     } else {
146         if (endptr != NULL)
147             *endptr = NULL;
148         return JSON_ERR_MISC;
149     }
150     /*@+compdef +nullstate@*/
151     return status;
152 }
153
154 /* ais_json.c ends here */