ais_json.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /****************************************************************************
  2. NAME
  3. ais_json.c - deserialize AIS JSON
  4. DESCRIPTION
  5. This module uses the generic JSON parser to get data from AIS
  6. representations to libgps structures.
  7. This file is Copyright 2010 by the GPSD project
  8. SPDX-License-Identifier: BSD-2-clause
  9. ***************************************************************************/
  10. #include "gpsd_config.h" /* must be before all includes */
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdbool.h>
  14. #include <stdlib.h>
  15. #include <stddef.h>
  16. #include <time.h>
  17. #include "gps.h"
  18. #include "json.h"
  19. #ifdef SOCKET_EXPORT_ENABLE
  20. #include "libgps.h"
  21. /* kluge because we don't want to include gpsd.h here */
  22. extern int gpsd_hexpack(const char *, char *, size_t);
  23. static void lenhex_unpack(const char *from,
  24. size_t * plen, char *to, size_t maxlen)
  25. {
  26. char *colon = strchr(from, ':');
  27. *plen = (size_t) atoi(from);
  28. if (colon != NULL)
  29. (void)gpsd_hexpack(colon + 1, to, maxlen);
  30. }
  31. int json_ais_read(const char *buf,
  32. char *path, size_t pathlen, struct ais_t *ais,
  33. const char **endptr)
  34. {
  35. /* collected but not actually used yet */
  36. bool scaled;
  37. #define AIS_HEADER \
  38. {"class", t_check, .dflt.check = "AIS"}, \
  39. {"type", t_uinteger, .addr.uinteger = &ais->type}, \
  40. {"device", t_string, .addr.string = path, \
  41. .len = pathlen}, \
  42. {"repeat", t_uinteger, .addr.uinteger = &ais->repeat}, \
  43. {"scaled", t_boolean, .addr.boolean = &scaled, \
  44. .dflt.boolean = false}, \
  45. {"mmsi", t_uinteger, .addr.uinteger = &ais->mmsi},
  46. #define AIS_TYPE6 \
  47. {"seqno", t_uinteger, .addr.uinteger = &ais->type6.seqno,\
  48. .dflt.uinteger = 0},\
  49. {"dest_mmsi", t_uinteger, .addr.uinteger = &ais->type6.dest_mmsi,\
  50. .dflt.uinteger = 0},\
  51. {"retransmit", t_boolean, .addr.boolean = &ais->type6.retransmit,\
  52. .dflt.boolean = false},\
  53. {"dac", t_uinteger, .addr.uinteger = &ais->type6.dac,\
  54. .dflt.uinteger = 0},\
  55. {"fid", t_uinteger, .addr.uinteger = &ais->type6.fid,\
  56. .dflt.uinteger = 0},
  57. #define AIS_TYPE8 \
  58. {"dac", t_uinteger, .addr.uinteger = &ais->type8.dac,\
  59. .dflt.uinteger = 0},\
  60. {"fid", t_uinteger, .addr.uinteger = &ais->type8.fid,\
  61. .dflt.uinteger = 0},
  62. int status;
  63. #include "ais_json.i" /* JSON parser template structures */
  64. #undef AIS_HEADER
  65. memset(ais, '\0', sizeof(struct ais_t));
  66. if (strstr(buf, "\"type\":1,") != NULL
  67. || strstr(buf, "\"type\":2,") != NULL
  68. || strstr(buf, "\"type\":3,") != NULL) {
  69. status = json_read_object(buf, json_ais1, endptr);
  70. } else if (strstr(buf, "\"type\":4,") != NULL
  71. || strstr(buf, "\"type\":11,") != NULL) {
  72. status = json_read_object(buf, json_ais4, endptr);
  73. if (status == 0) {
  74. ais->type4.year = AIS_YEAR_NOT_AVAILABLE;
  75. ais->type4.month = AIS_MONTH_NOT_AVAILABLE;
  76. ais->type4.day = AIS_DAY_NOT_AVAILABLE;
  77. ais->type4.hour = AIS_HOUR_NOT_AVAILABLE;
  78. ais->type4.minute = AIS_MINUTE_NOT_AVAILABLE;
  79. ais->type4.second = AIS_SECOND_NOT_AVAILABLE;
  80. /* We use %09u for the date to allow for dodgy years (>9999)
  81. * to go through. */
  82. // cppcheck-suppress uninitvar
  83. (void)sscanf(timestamp, "%09u-%02u-%02uT%02u:%02u:%02uZ",
  84. &ais->type4.year,
  85. &ais->type4.month,
  86. &ais->type4.day,
  87. &ais->type4.hour,
  88. &ais->type4.minute,
  89. &ais->type4.second);
  90. }
  91. } else if (strstr(buf, "\"type\":5,") != NULL) {
  92. status = json_read_object(buf, json_ais5, endptr);
  93. if (status == 0) {
  94. ais->type5.month = AIS_MONTH_NOT_AVAILABLE;
  95. ais->type5.day = AIS_DAY_NOT_AVAILABLE;
  96. ais->type5.hour = AIS_HOUR_NOT_AVAILABLE;
  97. ais->type5.minute = AIS_MINUTE_NOT_AVAILABLE;
  98. // cppcheck-suppress uninitvar
  99. (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
  100. &ais->type5.month,
  101. &ais->type5.day,
  102. &ais->type5.hour,
  103. &ais->type5.minute);
  104. }
  105. } else if (strstr(buf, "\"type\":6,") != NULL) {
  106. bool structured = false;
  107. if (strstr(buf, "\"dac\":1,") != NULL) {
  108. if (strstr(buf, "\"fid\":12,") != NULL) {
  109. status = json_read_object(buf, json_ais6_fid12, endptr);
  110. if (status == 0) {
  111. ais->type6.dac1fid12.lmonth = AIS_MONTH_NOT_AVAILABLE;
  112. ais->type6.dac1fid12.lday = AIS_DAY_NOT_AVAILABLE;
  113. ais->type6.dac1fid12.lhour = AIS_HOUR_NOT_AVAILABLE;
  114. ais->type6.dac1fid12.lminute = AIS_MINUTE_NOT_AVAILABLE;
  115. // cppcheck-suppress uninitvar
  116. (void)sscanf(departure, "%02u-%02uT%02u:%02uZ",
  117. &ais->type6.dac1fid12.lmonth,
  118. &ais->type6.dac1fid12.lday,
  119. &ais->type6.dac1fid12.lhour,
  120. &ais->type6.dac1fid12.lminute);
  121. ais->type6.dac1fid12.nmonth = AIS_MONTH_NOT_AVAILABLE;
  122. ais->type6.dac1fid12.nday = AIS_DAY_NOT_AVAILABLE;
  123. ais->type6.dac1fid12.nhour = AIS_HOUR_NOT_AVAILABLE;
  124. ais->type6.dac1fid12.nminute = AIS_MINUTE_NOT_AVAILABLE;
  125. // cppcheck-suppress uninitvar
  126. (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
  127. &ais->type6.dac1fid12.nmonth,
  128. &ais->type6.dac1fid12.nday,
  129. &ais->type6.dac1fid12.nhour,
  130. &ais->type6.dac1fid12.nminute);
  131. }
  132. structured = true;
  133. }
  134. else if (strstr(buf, "\"fid\":15,") != NULL) {
  135. status = json_read_object(buf, json_ais6_fid15, endptr);
  136. structured = true;
  137. }
  138. else if (strstr(buf, "\"fid\":16,") != NULL) {
  139. status = json_read_object(buf, json_ais6_fid16, endptr);
  140. structured = true;
  141. }
  142. else if (strstr(buf, "\"fid\":18,") != NULL) {
  143. status = json_read_object(buf, json_ais6_fid18, endptr);
  144. if (status == 0) {
  145. ais->type6.dac1fid18.day = AIS_DAY_NOT_AVAILABLE;
  146. ais->type6.dac1fid18.hour = AIS_HOUR_NOT_AVAILABLE;
  147. ais->type6.dac1fid18.minute = AIS_MINUTE_NOT_AVAILABLE;
  148. // cppcheck-suppress uninitvar
  149. (void)sscanf(arrival, "%02u-%02uT%02u:%02uZ",
  150. &ais->type6.dac1fid18.month,
  151. &ais->type6.dac1fid18.day,
  152. &ais->type6.dac1fid18.hour,
  153. &ais->type6.dac1fid18.minute);
  154. }
  155. structured = true;
  156. }
  157. else if (strstr(buf, "\"fid\":20,") != NULL) {
  158. status = json_read_object(buf, json_ais6_fid20, endptr);
  159. if (status == 0) {
  160. ais->type6.dac1fid20.month = AIS_MONTH_NOT_AVAILABLE;
  161. ais->type6.dac1fid20.day = AIS_DAY_NOT_AVAILABLE;
  162. ais->type6.dac1fid20.hour = AIS_HOUR_NOT_AVAILABLE;
  163. ais->type6.dac1fid20.minute = AIS_MINUTE_NOT_AVAILABLE;
  164. // cppcheck-suppress uninitvar
  165. (void)sscanf(arrival, "%02u-%02uT%02u:%02uZ",
  166. &ais->type6.dac1fid20.month,
  167. &ais->type6.dac1fid20.day,
  168. &ais->type6.dac1fid20.hour,
  169. &ais->type6.dac1fid20.minute);
  170. }
  171. structured = true;
  172. }
  173. else if (strstr(buf, "\"fid\":25,") != NULL) {
  174. status = json_read_object(buf, json_ais6_fid25, endptr);
  175. structured = true;
  176. }
  177. else if (strstr(buf, "\"fid\":28,") != NULL) {
  178. status = json_read_object(buf, json_ais6_fid28, endptr);
  179. if (status == 0) {
  180. ais->type6.dac1fid28.month = AIS_MONTH_NOT_AVAILABLE;
  181. ais->type6.dac1fid28.day = AIS_DAY_NOT_AVAILABLE;
  182. ais->type6.dac1fid28.hour = AIS_HOUR_NOT_AVAILABLE;
  183. ais->type6.dac1fid28.minute = AIS_MINUTE_NOT_AVAILABLE;
  184. // cppcheck-suppress uninitvar
  185. (void)sscanf(start, "%02u-%02uT%02u:%02uZ",
  186. &ais->type6.dac1fid28.month,
  187. &ais->type6.dac1fid28.day,
  188. &ais->type6.dac1fid28.hour,
  189. &ais->type6.dac1fid28.minute);
  190. }
  191. structured = true;
  192. }
  193. else if (strstr(buf, "\"fid\":30,") != NULL) {
  194. status = json_read_object(buf, json_ais6_fid30, endptr);
  195. structured = true;
  196. }
  197. else if (strstr(buf, "\"fid\":32,") != NULL ||
  198. strstr(buf, "\"fid\":14,") != NULL) {
  199. status = json_read_object(buf, json_ais6_fid32, endptr);
  200. structured = true;
  201. }
  202. }
  203. else if (strstr(buf, "\"dac\":235,") != NULL ||
  204. strstr(buf, "\"dac\":250,") != NULL) {
  205. if (strstr(buf, "\"fid\":10,") != NULL) {
  206. status = json_read_object(buf, json_ais6_fid10, endptr);
  207. structured = true;
  208. }
  209. }
  210. else if (strstr(buf, "\"dac\":200,") != NULL) {
  211. if (strstr(buf, "\"fid\":21,") != NULL) {
  212. status = json_read_object(buf, json_ais6_fid21, endptr);
  213. structured = true;
  214. if (status == 0) {
  215. ais->type6.dac200fid21.month = AIS_MONTH_NOT_AVAILABLE;
  216. ais->type6.dac200fid21.day = AIS_DAY_NOT_AVAILABLE;
  217. ais->type6.dac200fid21.hour = AIS_HOUR_NOT_AVAILABLE;
  218. ais->type6.dac200fid21.minute = AIS_MINUTE_NOT_AVAILABLE;
  219. // cppcheck-suppress uninitvar
  220. (void)sscanf(eta, "%02u-%02uT%02u:%02u",
  221. &ais->type6.dac200fid21.month,
  222. &ais->type6.dac200fid21.day,
  223. &ais->type6.dac200fid21.hour,
  224. &ais->type6.dac200fid21.minute);
  225. }
  226. }
  227. else if (strstr(buf, "\"fid\":22,") != NULL) {
  228. status = json_read_object(buf, json_ais6_fid22, endptr);
  229. structured = true;
  230. if (status == 0) {
  231. ais->type6.dac200fid22.month = AIS_MONTH_NOT_AVAILABLE;
  232. ais->type6.dac200fid22.day = AIS_DAY_NOT_AVAILABLE;
  233. ais->type6.dac200fid22.hour = AIS_HOUR_NOT_AVAILABLE;
  234. ais->type6.dac200fid22.minute = AIS_MINUTE_NOT_AVAILABLE;
  235. // cppcheck-suppress uninitvar
  236. (void)sscanf(rta, "%02u-%02uT%02u:%02u",
  237. &ais->type6.dac200fid22.month,
  238. &ais->type6.dac200fid22.day,
  239. &ais->type6.dac200fid22.hour,
  240. &ais->type6.dac200fid22.minute);
  241. }
  242. }
  243. else if (strstr(buf, "\"fid\":55,") != NULL) {
  244. status = json_read_object(buf, json_ais6_fid55, endptr);
  245. structured = true;
  246. }
  247. }
  248. if (!structured) {
  249. status = json_read_object(buf, json_ais6, endptr);
  250. if (status == 0)
  251. lenhex_unpack(data, &ais->type6.bitcount,
  252. ais->type6.bitdata, sizeof(ais->type6.bitdata));
  253. }
  254. ais->type6.structured = structured;
  255. } else if (strstr(buf, "\"type\":7,") != NULL
  256. || strstr(buf, "\"type\":13,") != NULL) {
  257. status = json_read_object(buf, json_ais7, endptr);
  258. } else if (strstr(buf, "\"type\":8,") != NULL) {
  259. bool structured = false;
  260. if (strstr(buf, "\"dac\":1,") != NULL) {
  261. if (strstr(buf, "\"fid\":11,") != NULL) {
  262. status = json_read_object(buf, json_ais8_fid11, endptr);
  263. if (status == 0) {
  264. ais->type8.dac1fid11.day = AIS_DAY_NOT_AVAILABLE;
  265. ais->type8.dac1fid11.hour = AIS_HOUR_NOT_AVAILABLE;
  266. ais->type8.dac1fid11.minute = AIS_MINUTE_NOT_AVAILABLE;
  267. // cppcheck-suppress uninitvar
  268. (void)sscanf(timestamp, "%02uT%02u:%02uZ",
  269. &ais->type8.dac1fid11.day,
  270. &ais->type8.dac1fid11.hour,
  271. &ais->type8.dac1fid11.minute);
  272. }
  273. structured = true;
  274. }
  275. else if (strstr(buf, "\"fid\":13,") != NULL) {
  276. status = json_read_object(buf, json_ais8_fid13, endptr);
  277. if (status == 0) {
  278. ais->type8.dac1fid13.fmonth = AIS_MONTH_NOT_AVAILABLE;
  279. ais->type8.dac1fid13.fday = AIS_DAY_NOT_AVAILABLE;
  280. ais->type8.dac1fid13.fhour = AIS_HOUR_NOT_AVAILABLE;
  281. ais->type8.dac1fid13.fminute = AIS_MINUTE_NOT_AVAILABLE;
  282. // cppcheck-suppress uninitvar
  283. (void)sscanf(departure, "%02u-%02uT%02u:%02uZ",
  284. &ais->type8.dac1fid13.fmonth,
  285. &ais->type8.dac1fid13.fday,
  286. &ais->type8.dac1fid13.fhour,
  287. &ais->type8.dac1fid13.fminute);
  288. ais->type8.dac1fid13.tmonth = AIS_MONTH_NOT_AVAILABLE;
  289. ais->type8.dac1fid13.tday = AIS_DAY_NOT_AVAILABLE;
  290. ais->type8.dac1fid13.thour = AIS_HOUR_NOT_AVAILABLE;
  291. ais->type8.dac1fid13.tminute = AIS_MINUTE_NOT_AVAILABLE;
  292. // cppcheck-suppress uninitvar
  293. (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
  294. &ais->type8.dac1fid13.tmonth,
  295. &ais->type8.dac1fid13.tday,
  296. &ais->type8.dac1fid13.thour,
  297. &ais->type8.dac1fid13.tminute);
  298. }
  299. structured = true;
  300. }
  301. else if (strstr(buf, "\"fid\":15,") != NULL) {
  302. status = json_read_object(buf, json_ais8_fid15, endptr);
  303. structured = true;
  304. }
  305. else if (strstr(buf, "\"fid\":16,") != NULL) {
  306. status = json_read_object(buf, json_ais8_fid16, endptr);
  307. if (status == 0) {
  308. structured = true;
  309. }
  310. }
  311. else if (strstr(buf, "\"fid\":17,") != NULL) {
  312. status = json_read_object(buf, json_ais8_fid17, endptr);
  313. structured = true;
  314. }
  315. else if (strstr(buf, "\"fid\":19,") != NULL) {
  316. status = json_read_object(buf, json_ais8_fid19, endptr);
  317. structured = true;
  318. }
  319. else if (strstr(buf, "\"fid\":23,") != NULL) {
  320. status = json_read_object(buf, json_ais8_fid23, endptr);
  321. ais->type8.dac200fid23.start_year = AIS_YEAR_NOT_AVAILABLE;
  322. ais->type8.dac200fid23.start_month = AIS_MONTH_NOT_AVAILABLE;
  323. ais->type8.dac200fid23.start_day = AIS_DAY_NOT_AVAILABLE;
  324. ais->type8.dac200fid23.start_hour = AIS_HOUR_NOT_AVAILABLE;
  325. ais->type8.dac200fid23.start_minute = AIS_MINUTE_NOT_AVAILABLE;
  326. ais->type8.dac200fid23.end_year = AIS_YEAR_NOT_AVAILABLE;
  327. ais->type8.dac200fid23.end_month = AIS_MONTH_NOT_AVAILABLE;
  328. ais->type8.dac200fid23.end_day = AIS_DAY_NOT_AVAILABLE;
  329. ais->type8.dac200fid23.end_hour = AIS_HOUR_NOT_AVAILABLE;
  330. ais->type8.dac200fid23.end_minute = AIS_MINUTE_NOT_AVAILABLE;
  331. // cppcheck-suppress uninitvar
  332. (void)sscanf(start, "%09u-%02u-%02uT%02u:%02u",
  333. &ais->type8.dac200fid23.start_year,
  334. &ais->type8.dac200fid23.start_month,
  335. &ais->type8.dac200fid23.start_day,
  336. &ais->type8.dac200fid23.start_hour,
  337. &ais->type8.dac200fid23.start_minute);
  338. // cppcheck-suppress uninitvar
  339. (void)sscanf(end, "%09u-%02u-%02uT%02u:%02u",
  340. &ais->type8.dac200fid23.end_year,
  341. &ais->type8.dac200fid23.end_month,
  342. &ais->type8.dac200fid23.end_day,
  343. &ais->type8.dac200fid23.end_hour,
  344. &ais->type8.dac200fid23.end_minute);
  345. structured = true;
  346. }
  347. else if (strstr(buf, "\"fid\":24,") != NULL) {
  348. status = json_read_object(buf, json_ais8_fid24, endptr);
  349. structured = true;
  350. }
  351. else if (strstr(buf, "\"fid\":27,") != NULL) {
  352. status = json_read_object(buf, json_ais8_fid27, endptr);
  353. if (status == 0) {
  354. ais->type8.dac1fid27.month = AIS_MONTH_NOT_AVAILABLE;
  355. ais->type8.dac1fid27.day = AIS_DAY_NOT_AVAILABLE;
  356. ais->type8.dac1fid27.hour = AIS_HOUR_NOT_AVAILABLE;
  357. ais->type8.dac1fid27.minute = AIS_MINUTE_NOT_AVAILABLE;
  358. // cppcheck-suppress uninitvar
  359. (void)sscanf(start, "%02u-%02uT%02u:%02uZ",
  360. &ais->type8.dac1fid27.month,
  361. &ais->type8.dac1fid27.day,
  362. &ais->type8.dac1fid27.hour,
  363. &ais->type8.dac1fid27.minute);
  364. }
  365. structured = true;
  366. }
  367. else if (strstr(buf, "\"fid\":29,") != NULL) {
  368. status = json_read_object(buf, json_ais8_fid29, endptr);
  369. structured = true;
  370. }
  371. else if (strstr(buf, "\"fid\":31,") != NULL) {
  372. status = json_read_object(buf, json_ais8_fid31, endptr);
  373. if (status == 0) {
  374. ais->type8.dac1fid31.day = AIS_DAY_NOT_AVAILABLE;
  375. ais->type8.dac1fid31.hour = AIS_HOUR_NOT_AVAILABLE;
  376. ais->type8.dac1fid31.minute = AIS_MINUTE_NOT_AVAILABLE;
  377. // cppcheck-suppress uninitvar
  378. (void)sscanf(timestamp, "%02uT%02u:%02uZ",
  379. &ais->type8.dac1fid31.day,
  380. &ais->type8.dac1fid31.hour,
  381. &ais->type8.dac1fid31.minute);
  382. }
  383. structured = true;
  384. }
  385. }
  386. else if (strstr(buf, "\"dac\":200,") != NULL &&
  387. strstr(buf,"data")==NULL) {
  388. if (strstr(buf, "\"fid\":10,") != NULL) {
  389. status = json_read_object(buf, json_ais8_fid10, endptr);
  390. structured = true;
  391. }
  392. if (strstr(buf, "\"fid\":40,") != NULL) {
  393. status = json_read_object(buf, json_ais8_fid40, endptr);
  394. structured = true;
  395. }
  396. }
  397. if (!structured) {
  398. status = json_read_object(buf, json_ais8, endptr);
  399. if (status == 0)
  400. lenhex_unpack(data, &ais->type8.bitcount,
  401. ais->type8.bitdata, sizeof(ais->type8.bitdata));
  402. }
  403. ais->type8.structured = structured;
  404. } else if (strstr(buf, "\"type\":9,") != NULL) {
  405. status = json_read_object(buf, json_ais9, endptr);
  406. } else if (strstr(buf, "\"type\":10,") != NULL) {
  407. status = json_read_object(buf, json_ais10, endptr);
  408. } else if (strstr(buf, "\"type\":12,") != NULL) {
  409. status = json_read_object(buf, json_ais12, endptr);
  410. } else if (strstr(buf, "\"type\":14,") != NULL) {
  411. status = json_read_object(buf, json_ais14, endptr);
  412. } else if (strstr(buf, "\"type\":15,") != NULL) {
  413. status = json_read_object(buf, json_ais15, endptr);
  414. } else if (strstr(buf, "\"type\":16,") != NULL) {
  415. status = json_read_object(buf, json_ais16, endptr);
  416. } else if (strstr(buf, "\"type\":17,") != NULL) {
  417. status = json_read_object(buf, json_ais17, endptr);
  418. if (status == 0)
  419. lenhex_unpack(data, &ais->type17.bitcount,
  420. ais->type17.bitdata, sizeof(ais->type17.bitdata));
  421. } else if (strstr(buf, "\"type\":18,") != NULL) {
  422. status = json_read_object(buf, json_ais18, endptr);
  423. } else if (strstr(buf, "\"type\":19,") != NULL) {
  424. status = json_read_object(buf, json_ais19, endptr);
  425. } else if (strstr(buf, "\"type\":20,") != NULL) {
  426. status = json_read_object(buf, json_ais20, endptr);
  427. } else if (strstr(buf, "\"type\":21,") != NULL) {
  428. status = json_read_object(buf, json_ais21, endptr);
  429. } else if (strstr(buf, "\"type\":22,") != NULL) {
  430. status = json_read_object(buf, json_ais22, endptr);
  431. } else if (strstr(buf, "\"type\":23,") != NULL) {
  432. status = json_read_object(buf, json_ais23, endptr);
  433. } else if (strstr(buf, "\"type\":24,") != NULL) {
  434. status = json_read_object(buf, json_ais24, endptr);
  435. } else if (strstr(buf, "\"type\":25,") != NULL) {
  436. status = json_read_object(buf, json_ais25, endptr);
  437. if (status == 0)
  438. lenhex_unpack(data, &ais->type25.bitcount,
  439. ais->type25.bitdata, sizeof(ais->type25.bitdata));
  440. } else if (strstr(buf, "\"type\":26,") != NULL) {
  441. status = json_read_object(buf, json_ais26, endptr);
  442. if (status == 0)
  443. lenhex_unpack(data, &ais->type26.bitcount,
  444. ais->type26.bitdata, sizeof(ais->type26.bitdata));
  445. } else if (strstr(buf, "\"type\":27,") != NULL) {
  446. status = json_read_object(buf, json_ais27, endptr);
  447. } else {
  448. if (endptr != NULL)
  449. *endptr = NULL;
  450. return JSON_ERR_MISC;
  451. }
  452. return status;
  453. }
  454. #endif /* SOCKET_EXPORT_ENABLE */
  455. /* ais_json.c ends here */
  456. // vim: set expandtab shiftwidth=4