Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbos Watchdog TextLCD mbed ConfigFile
parser.c
00001 /* 00002 * 00003 * NMEA library 00004 * URL: http://nmea.sourceforge.net 00005 * Author: Tim (xtimor@gmail.com) 00006 * Licence: http://www.gnu.org/licenses/lgpl.html 00007 * $Id: parser.c 17 2008-03-11 11:56:11Z xtimor $ 00008 * 00009 */ 00010 00011 /** 00012 * \file parser.h 00013 */ 00014 00015 #include "nmea/tok.h " 00016 #include "nmea/parse.h" 00017 #include "nmea/parser.h " 00018 #include "nmea/context.h" 00019 00020 #include <string.h> 00021 #include <stdlib.h> 00022 00023 typedef struct _nmeaParserNODE 00024 { 00025 int packType; 00026 void *pack; 00027 struct _nmeaParserNODE *next_node; 00028 00029 } nmeaParserNODE; 00030 00031 /* 00032 * high level 00033 */ 00034 00035 /** 00036 * \brief Initialization of parser object 00037 * @return true (1) - success or false (0) - fail 00038 */ 00039 int nmea_parser_init(nmeaPARSER *parser) 00040 { 00041 int resv = 0; 00042 int buff_size = nmea_property()->parse_buff_size; 00043 00044 NMEA_ASSERT(parser); 00045 00046 if(buff_size < NMEA_MIN_PARSEBUFF) 00047 buff_size = NMEA_MIN_PARSEBUFF; 00048 00049 memset(parser, 0, sizeof(nmeaPARSER)); 00050 00051 if(0 == (parser->buffer = (unsigned char *)malloc(buff_size))) 00052 nmea_error("Insufficient memory!"); 00053 else 00054 { 00055 parser->buff_size = buff_size; 00056 resv = 1; 00057 } 00058 00059 return resv; 00060 } 00061 00062 /** 00063 * \brief Destroy parser object 00064 */ 00065 void nmea_parser_destroy(nmeaPARSER *parser) 00066 { 00067 NMEA_ASSERT(parser && parser->buffer); 00068 free(parser->buffer); 00069 nmea_parser_queue_clear(parser); 00070 memset(parser, 0, sizeof(nmeaPARSER)); 00071 } 00072 00073 /** 00074 * \brief Analysis of buffer and put results to information structure 00075 * @return Number of packets wos parsed 00076 */ 00077 int nmea_parse( 00078 nmeaPARSER *parser, 00079 const char *buff, int buff_sz, 00080 nmeaINFO *info 00081 ) 00082 { 00083 int ptype, nread = 0; 00084 void *pack = 0; 00085 00086 NMEA_ASSERT(parser && parser->buffer); 00087 00088 nmea_parser_push(parser, buff, buff_sz); 00089 00090 while(GPNON != (ptype = nmea_parser_pop(parser, &pack))) 00091 { 00092 nread++; 00093 00094 switch(ptype) 00095 { 00096 case GPGGA: 00097 nmea_GPGGA2info((nmeaGPGGA *)pack, info); 00098 break; 00099 case GPGSA: 00100 nmea_GPGSA2info((nmeaGPGSA *)pack, info); 00101 break; 00102 case GPGSV: 00103 nmea_GPGSV2info((nmeaGPGSV *)pack, info); 00104 break; 00105 case GPRMC: 00106 nmea_GPRMC2info((nmeaGPRMC *)pack, info); 00107 break; 00108 case GPVTG: 00109 nmea_GPVTG2info((nmeaGPVTG *)pack, info); 00110 break; 00111 }; 00112 00113 free(pack); 00114 } 00115 00116 return nread; 00117 } 00118 00119 /* 00120 * low level 00121 */ 00122 00123 int nmea_parser_real_push(nmeaPARSER *parser, const char *buff, int buff_sz) 00124 { 00125 int nparsed = 0, crc, sen_sz, ptype; 00126 nmeaParserNODE *node = 0; 00127 00128 NMEA_ASSERT(parser && parser->buffer); 00129 00130 /* clear unuse buffer (for debug) */ 00131 /* 00132 memset( 00133 parser->buffer + parser->buff_use, 0, 00134 parser->buff_size - parser->buff_use 00135 ); 00136 */ 00137 00138 /* add */ 00139 if(parser->buff_use + buff_sz >= parser->buff_size) 00140 nmea_parser_buff_clear(parser); 00141 00142 memcpy(parser->buffer + parser->buff_use, buff, buff_sz); 00143 parser->buff_use += buff_sz; 00144 00145 /* parse */ 00146 for(;;node = 0) 00147 { 00148 sen_sz = nmea_find_tail( 00149 (const char *)parser->buffer + nparsed, 00150 (int)parser->buff_use - nparsed, &crc); 00151 00152 if(!sen_sz) 00153 { 00154 if(nparsed) 00155 { 00156 memcpy( 00157 parser->buffer, 00158 parser->buffer + nparsed, 00159 parser->buff_use -= nparsed); 00160 break; 00161 } 00162 } 00163 else if(crc >= 0) 00164 { 00165 ptype = nmea_pack_type( 00166 (const char *)parser->buffer + nparsed + 1, 00167 parser->buff_use - nparsed - 1); 00168 00169 if(0 == (node = (nmeaParserNODE *)malloc(sizeof(nmeaParserNODE)))) 00170 goto mem_fail; 00171 00172 node->pack = 0; 00173 00174 switch(ptype) 00175 { 00176 case GPGGA: 00177 if(0 == (node->pack = malloc(sizeof(nmeaGPGGA)))) 00178 goto mem_fail; 00179 node->packType = GPGGA; 00180 if(!nmea_parse_GPGGA( 00181 (const char *)parser->buffer + nparsed, 00182 sen_sz, (nmeaGPGGA *)node->pack)) 00183 { 00184 free(node); 00185 node = 0; 00186 } 00187 break; 00188 case GPGSA: 00189 if(0 == (node->pack = malloc(sizeof(nmeaGPGSA)))) 00190 goto mem_fail; 00191 node->packType = GPGSA; 00192 if(!nmea_parse_GPGSA( 00193 (const char *)parser->buffer + nparsed, 00194 sen_sz, (nmeaGPGSA *)node->pack)) 00195 { 00196 free(node); 00197 node = 0; 00198 } 00199 break; 00200 case GPGSV: 00201 if(0 == (node->pack = malloc(sizeof(nmeaGPGSV)))) 00202 goto mem_fail; 00203 node->packType = GPGSV; 00204 if(!nmea_parse_GPGSV( 00205 (const char *)parser->buffer + nparsed, 00206 sen_sz, (nmeaGPGSV *)node->pack)) 00207 { 00208 free(node); 00209 node = 0; 00210 } 00211 break; 00212 case GPRMC: 00213 if(0 == (node->pack = malloc(sizeof(nmeaGPRMC)))) 00214 goto mem_fail; 00215 node->packType = GPRMC; 00216 if(!nmea_parse_GPRMC( 00217 (const char *)parser->buffer + nparsed, 00218 sen_sz, (nmeaGPRMC *)node->pack)) 00219 { 00220 free(node); 00221 node = 0; 00222 } 00223 break; 00224 case GPVTG: 00225 if(0 == (node->pack = malloc(sizeof(nmeaGPVTG)))) 00226 goto mem_fail; 00227 node->packType = GPVTG; 00228 if(!nmea_parse_GPVTG( 00229 (const char *)parser->buffer + nparsed, 00230 sen_sz, (nmeaGPVTG *)node->pack)) 00231 { 00232 free(node); 00233 node = 0; 00234 } 00235 break; 00236 default: 00237 free(node); 00238 node = 0; 00239 break; 00240 }; 00241 00242 if(node) 00243 { 00244 if(parser->end_node) 00245 ((nmeaParserNODE *)parser->end_node)->next_node = node; 00246 parser->end_node = node; 00247 if(!parser->top_node) 00248 parser->top_node = node; 00249 node->next_node = 0; 00250 } 00251 } 00252 00253 nparsed += sen_sz; 00254 } 00255 00256 return nparsed; 00257 00258 mem_fail: 00259 if(node) 00260 free(node); 00261 00262 nmea_error("Insufficient memory!"); 00263 00264 return -1; 00265 } 00266 00267 /** 00268 * \brief Analysis of buffer and keep results into parser 00269 * @return Number of bytes wos parsed from buffer 00270 */ 00271 int nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz) 00272 { 00273 int nparse, nparsed = 0; 00274 00275 do 00276 { 00277 if(buff_sz > parser->buff_size) 00278 nparse = parser->buff_size; 00279 else 00280 nparse = buff_sz; 00281 00282 nparsed += nmea_parser_real_push( 00283 parser, buff, nparse); 00284 00285 buff_sz -= nparse; 00286 00287 } while(buff_sz); 00288 00289 return nparsed; 00290 } 00291 00292 /** 00293 * \brief Get type of top packet keeped into parser 00294 * @return Type of packet 00295 * @see nmeaPACKTYPE 00296 */ 00297 int nmea_parser_top(nmeaPARSER *parser) 00298 { 00299 int retval = GPNON; 00300 nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node; 00301 00302 NMEA_ASSERT(parser && parser->buffer); 00303 00304 if(node) 00305 retval = node->packType; 00306 00307 return retval; 00308 } 00309 00310 /** 00311 * \brief Withdraw top packet from parser 00312 * @return Received packet type 00313 * @see nmeaPACKTYPE 00314 */ 00315 int nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr) 00316 { 00317 int retval = GPNON; 00318 nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node; 00319 00320 NMEA_ASSERT(parser && parser->buffer); 00321 00322 if(node) 00323 { 00324 *pack_ptr = node->pack; 00325 retval = node->packType; 00326 parser->top_node = node->next_node; 00327 if(!parser->top_node) 00328 parser->end_node = 0; 00329 free(node); 00330 } 00331 00332 return retval; 00333 } 00334 00335 /** 00336 * \brief Get top packet from parser without withdraw 00337 * @return Received packet type 00338 * @see nmeaPACKTYPE 00339 */ 00340 int nmea_parser_peek(nmeaPARSER *parser, void **pack_ptr) 00341 { 00342 int retval = GPNON; 00343 nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node; 00344 00345 NMEA_ASSERT(parser && parser->buffer); 00346 00347 if(node) 00348 { 00349 *pack_ptr = node->pack; 00350 retval = node->packType; 00351 } 00352 00353 return retval; 00354 } 00355 00356 /** 00357 * \brief Delete top packet from parser 00358 * @return Deleted packet type 00359 * @see nmeaPACKTYPE 00360 */ 00361 int nmea_parser_drop(nmeaPARSER *parser) 00362 { 00363 int retval = GPNON; 00364 nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node; 00365 00366 NMEA_ASSERT(parser && parser->buffer); 00367 00368 if(node) 00369 { 00370 if(node->pack) 00371 free(node->pack); 00372 retval = node->packType; 00373 parser->top_node = node->next_node; 00374 if(!parser->top_node) 00375 parser->end_node = 0; 00376 free(node); 00377 } 00378 00379 return retval; 00380 } 00381 00382 /** 00383 * \brief Clear cache of parser 00384 * @return true (1) - success 00385 */ 00386 int nmea_parser_buff_clear(nmeaPARSER *parser) 00387 { 00388 NMEA_ASSERT(parser && parser->buffer); 00389 parser->buff_use = 0; 00390 return 1; 00391 } 00392 00393 /** 00394 * \brief Clear packets queue into parser 00395 * @return true (1) - success 00396 */ 00397 int nmea_parser_queue_clear(nmeaPARSER *parser) 00398 { 00399 NMEA_ASSERT(parser); 00400 while(parser->top_node) 00401 nmea_parser_drop(parser); 00402 return 1; 00403 }
Generated on Thu Jul 14 2022 14:06:47 by
1.7.2