| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- /*
- *
- * NMEA library
- * URL: http://nmea.sourceforge.net
- * Author: Tim (xtimor@gmail.com)
- * Licence: http://www.gnu.org/licenses/lgpl.html
- * $Id: parser.c 17 2008-03-11 11:56:11Z xtimor $
- *
- */
- /**
- * \file parser.h
- */
- #include "nmea/tok.h"
- #include "nmea/parse.h"
- #include "nmea/parser.h"
- #include "nmea/context.h"
- #include <string.h>
- #include <stdlib.h>
- typedef struct _nmeaParserNODE
- {
- int packType;
- void *pack;
- struct _nmeaParserNODE *next_node;
- } nmeaParserNODE;
- /*
- * high level
- */
- /**
- * \brief Initialization of parser object
- * @return true (1) - success or false (0) - fail
- */
- int nmea_parser_init(nmeaPARSER *parser)
- {
- int resv = 0;
- int buff_size = nmea_property()->parse_buff_size;
- NMEA_ASSERT(parser);
- if(buff_size < NMEA_MIN_PARSEBUFF)
- buff_size = NMEA_MIN_PARSEBUFF;
- memset(parser, 0, sizeof(nmeaPARSER));
- if(0 == (parser->buffer = malloc(buff_size)))
- nmea_error("Insufficient memory!");
- else
- {
- parser->buff_size = buff_size;
- resv = 1;
- }
- return resv;
- }
- /**
- * \brief Destroy parser object
- */
- void nmea_parser_destroy(nmeaPARSER *parser)
- {
- NMEA_ASSERT(parser && parser->buffer);
- free(parser->buffer);
- nmea_parser_queue_clear(parser);
- memset(parser, 0, sizeof(nmeaPARSER));
- }
- /**
- * \brief Analysis of buffer and put results to information structure
- * @return Number of packets wos parsed
- */
- int nmea_parse(
- nmeaPARSER *parser,
- const char *buff, int buff_sz,
- nmeaINFO *info
- )
- {
- int ptype, nread = 0;
- void *pack = 0;
- NMEA_ASSERT(parser && parser->buffer);
-
- nmea_parser_push(parser, buff, buff_sz);
- while(GPNON != (ptype = nmea_parser_pop(parser, &pack)))
- {
- nread++;
- switch(ptype)
- {
- case GPGGA:
- nmea_GPGGA2info((nmeaGPGGA *)pack, info);
- break;
- case GPGSA:
- nmea_GPGSA2info((nmeaGPGSA *)pack, info);
- break;
- case GPGSV:
- nmea_GPGSV2info((nmeaGPGSV *)pack, info);
- break;
- case GPRMC:
- nmea_GPRMC2info((nmeaGPRMC *)pack, info);
- break;
- case GNRMC:
- nmea_GNRMC2info((nmeaGPRMC *)pack, info);
- break;
- case GPVTG:
- nmea_GPVTG2info((nmeaGPVTG *)pack, info);
- break;
- case GNGGA:
- //printf("nmea解析GNGGA成功:%s\n",info);
- nmea_GNGGA2info((nmeaGPGGA *)pack, info);
- break;
- case BDGSV:
- //printf("nmea解析BDGSV成功:%s\n",info);
- nmea_BDGSV2info((nmeaGPGSV *)pack, info);
- break;
- case GNGSA:
- nmea_GNGSA2info((nmeaGPGSA *)pack, info);
- break;
- };
- free(pack);
- }
- return nread;
- }
- /*
- * low level
- */
- int nmea_parser_real_push(nmeaPARSER *parser, const char *buff, int buff_sz)
- {
-
- int nparsed = 0, crc, sen_sz, ptype;
- nmeaParserNODE *node = 0;
- NMEA_ASSERT(parser && parser->buffer);
- /* clear unuse buffer (for debug) */
- /*
- memset(
- parser->buffer + parser->buff_use, 0,
- parser->buff_size - parser->buff_use
- );
- */
- /* add */
- if(parser->buff_use + buff_sz >= parser->buff_size)
- nmea_parser_buff_clear(parser);
- memcpy(parser->buffer + parser->buff_use, buff, buff_sz);
- parser->buff_use += buff_sz;
- /* parse */
- for(;;node = 0)
- {
- sen_sz = nmea_find_tail(
- (const char *)parser->buffer + nparsed,
- (int)parser->buff_use - nparsed, &crc);
-
- if(!sen_sz)
- {
- if(nparsed)
- memcpy(
- parser->buffer,
- parser->buffer + nparsed,
- parser->buff_use -= nparsed);
- break;
- }
- else if(crc >= 0)
- {
- ptype = nmea_pack_type(
- (const char *)parser->buffer + nparsed + 1,
- parser->buff_use - nparsed - 1);
- //printf("\n解析到nmea_parser_real_push:%d\n",ptype);
- if(0 == (node = malloc(sizeof(nmeaParserNODE))))
- goto mem_fail;
- node->pack = 0;
- switch(ptype)
- {
- case GPGGA:
- if(0 == (node->pack = malloc(sizeof(nmeaGPGGA))))
- goto mem_fail;
- node->packType = GPGGA;
- if(!nmea_parse_GPGGA(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPGGA *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- case GNGGA:
- if(0 == (node->pack = malloc(sizeof(nmeaGPGGA))))
- goto mem_fail;
- node->packType = GPGGA;
- if(!nmea_parse_GNGGA(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPGGA *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- case GPGSA:
- if(0 == (node->pack = malloc(sizeof(nmeaGPGSA))))
- goto mem_fail;
- node->packType = GPGSA;
- if(!nmea_parse_GPGSA(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPGSA *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- case GNGSA:
- if(0 == (node->pack = malloc(sizeof(nmeaGPGSA))))
- goto mem_fail;
- node->packType = GPGSA;
- if(!nmea_parse_GNGSA(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPGSA *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- case GPGSV:
- if(0 == (node->pack = malloc(sizeof(nmeaGPGSV))))
- goto mem_fail;
- node->packType = GPGSV;
- if(!nmea_parse_GPGSV(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPGSV *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- case BDGSV:
- if(0 == (node->pack = malloc(sizeof(nmeaGPGSV))))
- goto mem_fail;
- node->packType = BDGSV;
- if(!nmea_parse_BDGSV(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPGSV *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- case GPRMC:
- if(0 == (node->pack = malloc(sizeof(nmeaGPRMC))))
- goto mem_fail;
- node->packType = GPRMC;
- if(!nmea_parse_GPRMC(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPRMC *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- case GNRMC:
- if(0 == (node->pack = malloc(sizeof(nmeaGPRMC))))
- goto mem_fail;
- node->packType = GPRMC;
- if(!nmea_parse_GNRMC(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPRMC *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- case GPVTG:
- if(0 == (node->pack = malloc(sizeof(nmeaGPVTG))))
- goto mem_fail;
- node->packType = GPVTG;
- if(!nmea_parse_GPVTG(
- (const char *)parser->buffer + nparsed,
- sen_sz, (nmeaGPVTG *)node->pack))
- {
- free(node);
- node = 0;
- }
- break;
- default:
- free(node);
- node = 0;
- break;
- };
- if(node)
- {
- if(parser->end_node)
- ((nmeaParserNODE *)parser->end_node)->next_node = node;
- parser->end_node = node;
- if(!parser->top_node)
- parser->top_node = node;
- node->next_node = 0;
- }
- }
- nparsed += sen_sz;
- }
- return nparsed;
- mem_fail:
- if(node)
- free(node);
-
- nmea_error("Insufficient memory!");
- return -1;
- }
- /**
- * \brief Analysis of buffer and keep results into parser
- * @return Number of bytes wos parsed from buffer
- */
- int nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz)
- {
- int nparse, nparsed = 0;
- do
- {
- if(buff_sz > parser->buff_size)
- nparse = parser->buff_size;
- else
- nparse = buff_sz;
- nparsed += nmea_parser_real_push(
- parser, buff, nparse);
- buff_sz -= nparse;
- } while(buff_sz);
- return nparsed;
- }
- /**
- * \brief Get type of top packet keeped into parser
- * @return Type of packet
- * @see nmeaPACKTYPE
- */
- int nmea_parser_top(nmeaPARSER *parser)
- {
- int retval = GPNON;
- nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;
- NMEA_ASSERT(parser && parser->buffer);
- if(node)
- retval = node->packType;
- return retval;
- }
- /**
- * \brief Withdraw top packet from parser
- * @return Received packet type
- * @see nmeaPACKTYPE
- */
- int nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr)
- {
- int retval = GPNON;
- nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;
- NMEA_ASSERT(parser && parser->buffer);
- if(node)
- {
- *pack_ptr = node->pack;
- retval = node->packType;
- parser->top_node = node->next_node;
- if(!parser->top_node)
- parser->end_node = 0;
- free(node);
- }
- return retval;
- }
- /**
- * \brief Get top packet from parser without withdraw
- * @return Received packet type
- * @see nmeaPACKTYPE
- */
- int nmea_parser_peek(nmeaPARSER *parser, void **pack_ptr)
- {
- int retval = GPNON;
- nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;
- NMEA_ASSERT(parser && parser->buffer);
- if(node)
- {
- *pack_ptr = node->pack;
- retval = node->packType;
- }
- return retval;
- }
- /**
- * \brief Delete top packet from parser
- * @return Deleted packet type
- * @see nmeaPACKTYPE
- */
- int nmea_parser_drop(nmeaPARSER *parser)
- {
- int retval = GPNON;
- nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;
- NMEA_ASSERT(parser && parser->buffer);
- if(node)
- {
- if(node->pack)
- free(node->pack);
- retval = node->packType;
- parser->top_node = node->next_node;
- if(!parser->top_node)
- parser->end_node = 0;
- free(node);
- }
- return retval;
- }
- /**
- * \brief Clear cache of parser
- * @return true (1) - success
- */
- int nmea_parser_buff_clear(nmeaPARSER *parser)
- {
- NMEA_ASSERT(parser && parser->buffer);
- parser->buff_use = 0;
- return 1;
- }
- /**
- * \brief Clear packets queue into parser
- * @return true (1) - success
- */
- int nmea_parser_queue_clear(nmeaPARSER *parser)
- {
- NMEA_ASSERT(parser);
- while(parser->top_node)
- nmea_parser_drop(parser);
- return 1;
- }
|