Guido Ottaviani / Mbed 2 deprecated LeonardoMbos

Dependencies:   mbos Watchdog TextLCD mbed ConfigFile

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers parser.c Source File

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 }