/*
 *
 * NMEA library
 * URL: http://nmea.sourceforge.net
 * Author: Tim ( [email protected])
 * Licence: http://www.gnu.org/licenses/lgpl.html
 * $Id: parser.h 4 2007-08-27 13:11:03Z xtimor $
 *
 */
#ifndef __NMEA_PARSER_H__
#define __NMEA_PARSER_H__
#include "info.h"
#ifdef  __cplusplus 
extern "C" {
#endif
/*
 * high level   //高层?  封装了下面的低层?
 */
typedef struct _nmeaPARSER
{
    void *top_node;
    void *end_node;
    unsigned char *buffer;
    int buff_size;
    int buff_use;
} nmeaPARSER;  //链表的形式?
//具体详情还得看c文件
int     nmea_parser_init(nmeaPARSER *parser);
void    nmea_parser_destroy(nmeaPARSER *parser);
int     nmea_parse(
        nmeaPARSER *parser,
        const char *buff, int buff_sz,
        nmeaINFO *info
        );
/*
 * low level
 */
//类似堆栈的操作形式
int     nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz);
int     nmea_parser_top(nmeaPARSER *parser);
int     nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr);
int     nmea_parser_peek(nmeaPARSER *parser, void **pack_ptr);
int     nmea_parser_drop(nmeaPARSER *parser);
int     nmea_parser_buff_clear(nmeaPARSER *parser);
int     nmea_parser_queue_clear(nmeaPARSER *parser);
#ifdef  __cplusplus
}
#endif
#endif /* __NMEA_PARSER_H__ */
 
 
 
/*
 *
 * NMEA library
 * URL: http://nmea.sourceforge.net
 * Author: Tim ( [email protected])
 * 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
#include
//这里为什么有的定义在h文件中,而有的却写在c文件中呢?一般来说,写在h文件中的,是给别人看的,供别人调用,而写在c里面的只是自己内部调用。相当于c++的public和private关系。
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)))  // malloc!!!看看它哪里free??
        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);  // 这里free,,整的跟析构函数似的。前面的就相当于构造函数
    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 GPVTG:
            nmea_GPVTG2info((nmeaGPVTG *)pack, info);
            break;
        };
        free(pack);// 前面有malloc  吗》?
    }
    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);// 若是parser buff现存不足,则clear
    memcpy(parser->buffer + parser->buff_use, buff, buff_sz);// 否则就继续buf_use后,添加buff_size大小的buff
    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);
// 找nmea尾部
        if(!sen_sz)
        {
            if(nparsed)
                memcpy(
                parser->buffer,
                parser->buffer + nparsed,
                parser->buff_use -= nparsed);
            break;
        }
        else if(crc >= 0)  //存在crc,
        {
            ptype = nmea_pack_type(
                (const char *)parser->buffer + nparsed + 1,
                parser->buff_use - nparsed - 1);
            if(0 == (node = malloc(sizeof(nmeaParserNODE))))
                goto mem_fail;  // 申请内存失败,goto语句还是很有市场的
            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);   // 一定注意free,他这些本身函数中free,最后结尾还判断是否释放
                    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 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 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 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。为什么不先if,在free;貌似都很有自信。我看这个if结构很万能啊
                free(node);
                node = 0;  // 置零,,这是个精细的活
                break;
            };
            if(node)
            {  // 链表啊!!好像链表都要malloc和free。需要恶补一下连表的知识
                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
// push所有的数据,而前面的realpush是一次一个
 */
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);  // 因为top已经被pop,所以就要free
    }
    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;// 这个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);  //free,,相对于前面的pop,可以对比看一下?
        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;   // 把正在使用的buffer值清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);    // 为什么要while?这个praser又不是数组?只有一个元素才对,也就是说只有个一个top——node才对。。。??
    return 1;
}