ais_json.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  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 (c)2010-2018 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) to go through
  81. // cppcheck-suppress uninitvar
  82. (void)sscanf(timestamp, "%09u-%02u-%02uT%02u:%02u:%02uZ",
  83. &ais->type4.year,
  84. &ais->type4.month,
  85. &ais->type4.day,
  86. &ais->type4.hour,
  87. &ais->type4.minute,
  88. &ais->type4.second);
  89. }
  90. } else if (strstr(buf, "\"type\":5,") != NULL) {
  91. status = json_read_object(buf, json_ais5, endptr);
  92. if (status == 0) {
  93. ais->type5.month = AIS_MONTH_NOT_AVAILABLE;
  94. ais->type5.day = AIS_DAY_NOT_AVAILABLE;
  95. ais->type5.hour = AIS_HOUR_NOT_AVAILABLE;
  96. ais->type5.minute = AIS_MINUTE_NOT_AVAILABLE;
  97. // cppcheck-suppress uninitvar
  98. (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
  99. &ais->type5.month,
  100. &ais->type5.day,
  101. &ais->type5.hour,
  102. &ais->type5.minute);
  103. }
  104. } else if (strstr(buf, "\"type\":6,") != NULL) {
  105. bool structured = false;
  106. if (strstr(buf, "\"dac\":1,") != NULL) {
  107. if (strstr(buf, "\"fid\":12,") != NULL) {
  108. status = json_read_object(buf, json_ais6_fid12, endptr);
  109. if (status == 0) {
  110. ais->type6.dac1fid12.lmonth = AIS_MONTH_NOT_AVAILABLE;
  111. ais->type6.dac1fid12.lday = AIS_DAY_NOT_AVAILABLE;
  112. ais->type6.dac1fid12.lhour = AIS_HOUR_NOT_AVAILABLE;
  113. ais->type6.dac1fid12.lminute = AIS_MINUTE_NOT_AVAILABLE;
  114. // cppcheck-suppress uninitvar
  115. (void)sscanf(departure, "%02u-%02uT%02u:%02uZ",
  116. &ais->type6.dac1fid12.lmonth,
  117. &ais->type6.dac1fid12.lday,
  118. &ais->type6.dac1fid12.lhour,
  119. &ais->type6.dac1fid12.lminute);
  120. ais->type6.dac1fid12.nmonth = AIS_MONTH_NOT_AVAILABLE;
  121. ais->type6.dac1fid12.nday = AIS_DAY_NOT_AVAILABLE;
  122. ais->type6.dac1fid12.nhour = AIS_HOUR_NOT_AVAILABLE;
  123. ais->type6.dac1fid12.nminute = AIS_MINUTE_NOT_AVAILABLE;
  124. // cppcheck-suppress uninitvar
  125. (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
  126. &ais->type6.dac1fid12.nmonth,
  127. &ais->type6.dac1fid12.nday,
  128. &ais->type6.dac1fid12.nhour,
  129. &ais->type6.dac1fid12.nminute);
  130. }
  131. structured = true;
  132. }
  133. else if (strstr(buf, "\"fid\":15,") != NULL) {
  134. status = json_read_object(buf, json_ais6_fid15, endptr);
  135. structured = true;
  136. }
  137. else if (strstr(buf, "\"fid\":16,") != NULL) {
  138. status = json_read_object(buf, json_ais6_fid16, endptr);
  139. structured = true;
  140. }
  141. else if (strstr(buf, "\"fid\":18,") != NULL) {
  142. status = json_read_object(buf, json_ais6_fid18, endptr);
  143. if (status == 0) {
  144. ais->type6.dac1fid18.day = AIS_DAY_NOT_AVAILABLE;
  145. ais->type6.dac1fid18.hour = AIS_HOUR_NOT_AVAILABLE;
  146. ais->type6.dac1fid18.minute = AIS_MINUTE_NOT_AVAILABLE;
  147. // cppcheck-suppress uninitvar
  148. (void)sscanf(arrival, "%02u-%02uT%02u:%02uZ",
  149. &ais->type6.dac1fid18.month,
  150. &ais->type6.dac1fid18.day,
  151. &ais->type6.dac1fid18.hour,
  152. &ais->type6.dac1fid18.minute);
  153. }
  154. structured = true;
  155. }
  156. else if (strstr(buf, "\"fid\":20,") != NULL) {
  157. status = json_read_object(buf, json_ais6_fid20, endptr);
  158. if (status == 0) {
  159. ais->type6.dac1fid20.month = AIS_MONTH_NOT_AVAILABLE;
  160. ais->type6.dac1fid20.day = AIS_DAY_NOT_AVAILABLE;
  161. ais->type6.dac1fid20.hour = AIS_HOUR_NOT_AVAILABLE;
  162. ais->type6.dac1fid20.minute = AIS_MINUTE_NOT_AVAILABLE;
  163. // cppcheck-suppress uninitvar
  164. (void)sscanf(arrival, "%02u-%02uT%02u:%02uZ",
  165. &ais->type6.dac1fid20.month,
  166. &ais->type6.dac1fid20.day,
  167. &ais->type6.dac1fid20.hour,
  168. &ais->type6.dac1fid20.minute);
  169. }
  170. structured = true;
  171. }
  172. else if (strstr(buf, "\"fid\":25,") != NULL) {
  173. status = json_read_object(buf, json_ais6_fid25, endptr);
  174. structured = true;
  175. }
  176. else if (strstr(buf, "\"fid\":28,") != NULL) {
  177. status = json_read_object(buf, json_ais6_fid28, endptr);
  178. if (status == 0) {
  179. ais->type6.dac1fid28.month = AIS_MONTH_NOT_AVAILABLE;
  180. ais->type6.dac1fid28.day = AIS_DAY_NOT_AVAILABLE;
  181. ais->type6.dac1fid28.hour = AIS_HOUR_NOT_AVAILABLE;
  182. ais->type6.dac1fid28.minute = AIS_MINUTE_NOT_AVAILABLE;
  183. // cppcheck-suppress uninitvar
  184. (void)sscanf(start, "%02u-%02uT%02u:%02uZ",
  185. &ais->type6.dac1fid28.month,
  186. &ais->type6.dac1fid28.day,
  187. &ais->type6.dac1fid28.hour,
  188. &ais->type6.dac1fid28.minute);
  189. }
  190. structured = true;
  191. }
  192. else if (strstr(buf, "\"fid\":30,") != NULL) {
  193. status = json_read_object(buf, json_ais6_fid30, endptr);
  194. structured = true;
  195. }
  196. else if (strstr(buf, "\"fid\":32,") != NULL || strstr(buf, "\"fid\":14,") != NULL) {
  197. status = json_read_object(buf, json_ais6_fid32, endptr);
  198. structured = true;
  199. }
  200. }
  201. else if (strstr(buf, "\"dac\":235,") != NULL || strstr(buf, "\"dac\":250,") != NULL) {
  202. if (strstr(buf, "\"fid\":10,") != NULL) {
  203. status = json_read_object(buf, json_ais6_fid10, endptr);
  204. structured = true;
  205. }
  206. }
  207. else if (strstr(buf, "\"dac\":200,") != NULL) {
  208. if (strstr(buf, "\"fid\":21,") != NULL) {
  209. status = json_read_object(buf, json_ais6_fid21, endptr);
  210. structured = true;
  211. if (status == 0) {
  212. ais->type6.dac200fid21.month = AIS_MONTH_NOT_AVAILABLE;
  213. ais->type6.dac200fid21.day = AIS_DAY_NOT_AVAILABLE;
  214. ais->type6.dac200fid21.hour = AIS_HOUR_NOT_AVAILABLE;
  215. ais->type6.dac200fid21.minute = AIS_MINUTE_NOT_AVAILABLE;
  216. // cppcheck-suppress uninitvar
  217. (void)sscanf(eta, "%02u-%02uT%02u:%02u",
  218. &ais->type6.dac200fid21.month,
  219. &ais->type6.dac200fid21.day,
  220. &ais->type6.dac200fid21.hour,
  221. &ais->type6.dac200fid21.minute);
  222. }
  223. }
  224. else if (strstr(buf, "\"fid\":22,") != NULL) {
  225. status = json_read_object(buf, json_ais6_fid22, endptr);
  226. structured = true;
  227. if (status == 0) {
  228. ais->type6.dac200fid22.month = AIS_MONTH_NOT_AVAILABLE;
  229. ais->type6.dac200fid22.day = AIS_DAY_NOT_AVAILABLE;
  230. ais->type6.dac200fid22.hour = AIS_HOUR_NOT_AVAILABLE;
  231. ais->type6.dac200fid22.minute = AIS_MINUTE_NOT_AVAILABLE;
  232. // cppcheck-suppress uninitvar
  233. (void)sscanf(rta, "%02u-%02uT%02u:%02u",
  234. &ais->type6.dac200fid22.month,
  235. &ais->type6.dac200fid22.day,
  236. &ais->type6.dac200fid22.hour,
  237. &ais->type6.dac200fid22.minute);
  238. }
  239. }
  240. else if (strstr(buf, "\"fid\":55,") != NULL) {
  241. status = json_read_object(buf, json_ais6_fid55, endptr);
  242. structured = true;
  243. }
  244. }
  245. if (!structured) {
  246. status = json_read_object(buf, json_ais6, endptr);
  247. if (status == 0)
  248. lenhex_unpack(data, &ais->type6.bitcount,
  249. ais->type6.bitdata, sizeof(ais->type6.bitdata));
  250. }
  251. ais->type6.structured = structured;
  252. } else if (strstr(buf, "\"type\":7,") != NULL
  253. || strstr(buf, "\"type\":13,") != NULL) {
  254. status = json_read_object(buf, json_ais7, endptr);
  255. } else if (strstr(buf, "\"type\":8,") != NULL) {
  256. bool structured = false;
  257. if (strstr(buf, "\"dac\":1,") != NULL) {
  258. if (strstr(buf, "\"fid\":11,") != NULL) {
  259. status = json_read_object(buf, json_ais8_fid11, endptr);
  260. if (status == 0) {
  261. ais->type8.dac1fid11.day = AIS_DAY_NOT_AVAILABLE;
  262. ais->type8.dac1fid11.hour = AIS_HOUR_NOT_AVAILABLE;
  263. ais->type8.dac1fid11.minute = AIS_MINUTE_NOT_AVAILABLE;
  264. // cppcheck-suppress uninitvar
  265. (void)sscanf(timestamp, "%02uT%02u:%02uZ",
  266. &ais->type8.dac1fid11.day,
  267. &ais->type8.dac1fid11.hour,
  268. &ais->type8.dac1fid11.minute);
  269. }
  270. structured = true;
  271. }
  272. else if (strstr(buf, "\"fid\":13,") != NULL) {
  273. status = json_read_object(buf, json_ais8_fid13, endptr);
  274. if (status == 0) {
  275. ais->type8.dac1fid13.fmonth = AIS_MONTH_NOT_AVAILABLE;
  276. ais->type8.dac1fid13.fday = AIS_DAY_NOT_AVAILABLE;
  277. ais->type8.dac1fid13.fhour = AIS_HOUR_NOT_AVAILABLE;
  278. ais->type8.dac1fid13.fminute = AIS_MINUTE_NOT_AVAILABLE;
  279. // cppcheck-suppress uninitvar
  280. (void)sscanf(departure, "%02u-%02uT%02u:%02uZ",
  281. &ais->type8.dac1fid13.fmonth,
  282. &ais->type8.dac1fid13.fday,
  283. &ais->type8.dac1fid13.fhour,
  284. &ais->type8.dac1fid13.fminute);
  285. ais->type8.dac1fid13.tmonth = AIS_MONTH_NOT_AVAILABLE;
  286. ais->type8.dac1fid13.tday = AIS_DAY_NOT_AVAILABLE;
  287. ais->type8.dac1fid13.thour = AIS_HOUR_NOT_AVAILABLE;
  288. ais->type8.dac1fid13.tminute = AIS_MINUTE_NOT_AVAILABLE;
  289. // cppcheck-suppress uninitvar
  290. (void)sscanf(eta, "%02u-%02uT%02u:%02uZ",
  291. &ais->type8.dac1fid13.tmonth,
  292. &ais->type8.dac1fid13.tday,
  293. &ais->type8.dac1fid13.thour,
  294. &ais->type8.dac1fid13.tminute);
  295. }
  296. structured = true;
  297. }
  298. else if (strstr(buf, "\"fid\":15,") != NULL) {
  299. status = json_read_object(buf, json_ais8_fid15, endptr);
  300. structured = true;
  301. }
  302. else if (strstr(buf, "\"fid\":16,") != NULL) {
  303. status = json_read_object(buf, json_ais8_fid16, endptr);
  304. if (status == 0) {
  305. structured = true;
  306. }
  307. }
  308. else if (strstr(buf, "\"fid\":17,") != NULL) {
  309. status = json_read_object(buf, json_ais8_fid17, endptr);
  310. structured = true;
  311. }
  312. else if (strstr(buf, "\"fid\":19,") != NULL) {
  313. status = json_read_object(buf, json_ais8_fid19, endptr);
  314. structured = true;
  315. }
  316. else if (strstr(buf, "\"fid\":23,") != NULL) {
  317. status = json_read_object(buf, json_ais8_fid23, endptr);
  318. ais->type8.dac200fid23.start_year = AIS_YEAR_NOT_AVAILABLE;
  319. ais->type8.dac200fid23.start_month = AIS_MONTH_NOT_AVAILABLE;
  320. ais->type8.dac200fid23.start_day = AIS_DAY_NOT_AVAILABLE;
  321. ais->type8.dac200fid23.start_hour = AIS_HOUR_NOT_AVAILABLE;
  322. ais->type8.dac200fid23.start_minute = AIS_MINUTE_NOT_AVAILABLE;
  323. ais->type8.dac200fid23.end_year = AIS_YEAR_NOT_AVAILABLE;
  324. ais->type8.dac200fid23.end_month = AIS_MONTH_NOT_AVAILABLE;
  325. ais->type8.dac200fid23.end_day = AIS_DAY_NOT_AVAILABLE;
  326. ais->type8.dac200fid23.end_hour = AIS_HOUR_NOT_AVAILABLE;
  327. ais->type8.dac200fid23.end_minute = AIS_MINUTE_NOT_AVAILABLE;
  328. // cppcheck-suppress uninitvar
  329. (void)sscanf(start, "%09u-%02u-%02uT%02u:%02u",
  330. &ais->type8.dac200fid23.start_year,
  331. &ais->type8.dac200fid23.start_month,
  332. &ais->type8.dac200fid23.start_day,
  333. &ais->type8.dac200fid23.start_hour,
  334. &ais->type8.dac200fid23.start_minute);
  335. // cppcheck-suppress uninitvar
  336. (void)sscanf(end, "%09u-%02u-%02uT%02u:%02u",
  337. &ais->type8.dac200fid23.end_year,
  338. &ais->type8.dac200fid23.end_month,
  339. &ais->type8.dac200fid23.end_day,
  340. &ais->type8.dac200fid23.end_hour,
  341. &ais->type8.dac200fid23.end_minute);
  342. structured = true;
  343. }
  344. else if (strstr(buf, "\"fid\":24,") != NULL) {
  345. status = json_read_object(buf, json_ais8_fid24, endptr);
  346. structured = true;
  347. }
  348. else if (strstr(buf, "\"fid\":27,") != NULL) {
  349. status = json_read_object(buf, json_ais8_fid27, endptr);
  350. if (status == 0) {
  351. ais->type8.dac1fid27.month = AIS_MONTH_NOT_AVAILABLE;
  352. ais->type8.dac1fid27.day = AIS_DAY_NOT_AVAILABLE;
  353. ais->type8.dac1fid27.hour = AIS_HOUR_NOT_AVAILABLE;
  354. ais->type8.dac1fid27.minute = AIS_MINUTE_NOT_AVAILABLE;
  355. // cppcheck-suppress uninitvar
  356. (void)sscanf(start, "%02u-%02uT%02u:%02uZ",
  357. &ais->type8.dac1fid27.month,
  358. &ais->type8.dac1fid27.day,
  359. &ais->type8.dac1fid27.hour,
  360. &ais->type8.dac1fid27.minute);
  361. }
  362. structured = true;
  363. }
  364. else if (strstr(buf, "\"fid\":29,") != NULL) {
  365. status = json_read_object(buf, json_ais8_fid29, endptr);
  366. structured = true;
  367. }
  368. else if (strstr(buf, "\"fid\":31,") != NULL) {
  369. status = json_read_object(buf, json_ais8_fid31, endptr);
  370. if (status == 0) {
  371. ais->type8.dac1fid31.day = AIS_DAY_NOT_AVAILABLE;
  372. ais->type8.dac1fid31.hour = AIS_HOUR_NOT_AVAILABLE;
  373. ais->type8.dac1fid31.minute = AIS_MINUTE_NOT_AVAILABLE;
  374. // cppcheck-suppress uninitvar
  375. (void)sscanf(timestamp, "%02uT%02u:%02uZ",
  376. &ais->type8.dac1fid31.day,
  377. &ais->type8.dac1fid31.hour,
  378. &ais->type8.dac1fid31.minute);
  379. }
  380. structured = true;
  381. }
  382. }
  383. else if (strstr(buf, "\"dac\":200,") != NULL && strstr(buf,"data")==NULL) {
  384. if (strstr(buf, "\"fid\":10,") != NULL) {
  385. status = json_read_object(buf, json_ais8_fid10, endptr);
  386. structured = true;
  387. }
  388. if (strstr(buf, "\"fid\":40,") != NULL) {
  389. status = json_read_object(buf, json_ais8_fid40, endptr);
  390. structured = true;
  391. }
  392. }
  393. if (!structured) {
  394. status = json_read_object(buf, json_ais8, endptr);
  395. if (status == 0)
  396. lenhex_unpack(data, &ais->type8.bitcount,
  397. ais->type8.bitdata, sizeof(ais->type8.bitdata));
  398. }
  399. ais->type8.structured = structured;
  400. } else if (strstr(buf, "\"type\":9,") != NULL) {
  401. status = json_read_object(buf, json_ais9, endptr);
  402. } else if (strstr(buf, "\"type\":10,") != NULL) {
  403. status = json_read_object(buf, json_ais10, endptr);
  404. } else if (strstr(buf, "\"type\":12,") != NULL) {
  405. status = json_read_object(buf, json_ais12, endptr);
  406. } else if (strstr(buf, "\"type\":14,") != NULL) {
  407. status = json_read_object(buf, json_ais14, endptr);
  408. } else if (strstr(buf, "\"type\":15,") != NULL) {
  409. status = json_read_object(buf, json_ais15, endptr);
  410. } else if (strstr(buf, "\"type\":16,") != NULL) {
  411. status = json_read_object(buf, json_ais16, endptr);
  412. } else if (strstr(buf, "\"type\":17,") != NULL) {
  413. status = json_read_object(buf, json_ais17, endptr);
  414. if (status == 0)
  415. lenhex_unpack(data, &ais->type17.bitcount,
  416. ais->type17.bitdata, sizeof(ais->type17.bitdata));
  417. } else if (strstr(buf, "\"type\":18,") != NULL) {
  418. status = json_read_object(buf, json_ais18, endptr);
  419. } else if (strstr(buf, "\"type\":19,") != NULL) {
  420. status = json_read_object(buf, json_ais19, endptr);
  421. } else if (strstr(buf, "\"type\":20,") != NULL) {
  422. status = json_read_object(buf, json_ais20, endptr);
  423. } else if (strstr(buf, "\"type\":21,") != NULL) {
  424. status = json_read_object(buf, json_ais21, endptr);
  425. } else if (strstr(buf, "\"type\":22,") != NULL) {
  426. status = json_read_object(buf, json_ais22, endptr);
  427. } else if (strstr(buf, "\"type\":23,") != NULL) {
  428. status = json_read_object(buf, json_ais23, endptr);
  429. } else if (strstr(buf, "\"type\":24,") != NULL) {
  430. status = json_read_object(buf, json_ais24, endptr);
  431. } else if (strstr(buf, "\"type\":25,") != NULL) {
  432. status = json_read_object(buf, json_ais25, endptr);
  433. if (status == 0)
  434. lenhex_unpack(data, &ais->type25.bitcount,
  435. ais->type25.bitdata, sizeof(ais->type25.bitdata));
  436. } else if (strstr(buf, "\"type\":26,") != NULL) {
  437. status = json_read_object(buf, json_ais26, endptr);
  438. if (status == 0)
  439. lenhex_unpack(data, &ais->type26.bitcount,
  440. ais->type26.bitdata, sizeof(ais->type26.bitdata));
  441. } else if (strstr(buf, "\"type\":27,") != NULL) {
  442. status = json_read_object(buf, json_ais27, endptr);
  443. } else {
  444. if (endptr != NULL)
  445. *endptr = NULL;
  446. return JSON_ERR_MISC;
  447. }
  448. return status;
  449. }
  450. #endif /* SOCKET_EXPORT_ENABLE */
  451. /* ais_json.c ends here */