C/C++编程:读取配置文件

1059 篇文章 278 订阅

编程技巧

如果一个函数内有多个内存位置需要释放

     acl_xinetd_nv_pair *acl_xinetd_cfg_parser::nv_pair_new(const char *name, const char *value){
        acl_xinetd_nv_pair * pair = (acl_xinetd_nv_pair *) calloc(1, sizeof(acl_xinetd_nv_pair));
        if (pair == NULL)
            return (NULL);

#undef	ERETURN
#define	ERETURN(x) { \
	if (pair) { \
		if (pair->name) \
			free(pair->name); \
		if (pair->value) \
			free(pair->value); \
		free(pair); \
		pair = NULL; \
	} \
	return (x); \
}
        pair->name = strdup(name);
        if (pair->name == NULL){
            ERETURN (NULL);
        }

        pair->value = strdup(value);
        if (pair->value == NULL){
            ERETURN (NULL);
        }
        return pair;
    }

版本1

读取格式类似:

a_count = 1
b_count = 20
a_count = 10

思路

  • 先将文件所有内容读入文件
  • 然后一行一行解析
    • 先截成一行一行的
    • 然后每一行去掉多余的\r\n空格之类的东西
    • 这样就可以得到一个key和一个value
  • 看当前nv_array中有没有相应key:
    • 有:更新
    • 没有:塞入
      • 先生成key
      • 然后塞入

源码

//
// Created by oceanstar on 2021/8/18.
//

#ifndef OCEANSTAR_HTTP_ACL_XINETD_CFG_PARSER_H
#define OCEANSTAR_HTTP_ACL_XINETD_CFG_PARSER_H

#include <log.h>
#include <stream/vstream.h>
#include <memory/acl_mystring.h>

namespace oceanstar{

    struct acl_xinetd_nv_pair{
        char *name = NULL;
        char *value = NULL;
    };


    class acl_xinetd_cfg_parser{
    private:
        std::vector<acl_xinetd_nv_pair *> nv_array;
    private:
        static void nv_pair_free( acl_xinetd_nv_pair * pair);
        static acl_xinetd_nv_pair *nv_pair_new(const char *name, const char *value);
        static void nv_pair_update( acl_xinetd_nv_pair * pair, const char *value);
    public:
        ~acl_xinetd_cfg_parser(){
            for(auto & pair : nv_array){
                nv_pair_free(pair);
            }
        }

        std::vector<acl_xinetd_nv_pair*>& get_nv_array(){
            return nv_array;
        }
    public:
        int xinetd_cfg_parse(char *line_nonl);
    };

    inline acl_xinetd_cfg_parser * acl_xinetd_cfg_malloc(){
        return new acl_xinetd_cfg_parser;
    }

    inline void acl_xinetd_cfg_free(acl_xinetd_cfg_parser * parser){
        delete parser;
    }

    /**
     * 功能: 读取配置文件并进行解析
     * @param pathname 配置文件的文件名
     * @return 已经解析了配置文件的结构指针, 必须使用acl_xinetd_cfg_free释放
     */
    acl_xinetd_cfg_parser * acl_xinetd_cfg_load(const char *pathname);

}
#endif //OCEANSTAR_HTTP_ACL_XINETD_CFG_PARSER_H

//
// Created by oceanstar on 2021/8/18.
//

#include "acl_xinetd_cfg_parser.h"


namespace oceanstar{


     void acl_xinetd_cfg_parser::nv_pair_free( acl_xinetd_nv_pair * pair){
         if(pair){
             if(pair->name){
                 free(pair->name);
             }
             if(pair->value){
                 free(pair->value);
             }

             free(pair);
             pair = NULL;
         }
    }

    void acl_xinetd_cfg_parser::nv_pair_update( acl_xinetd_nv_pair * pair, const char *value){
         if(pair == NULL){
             return;
         }

         if(pair->value && *pair->value){
             free(pair->value);
         }

         if(value == NULL || *value == 0){
             pair->value = NULL;
         }else{
             pair->value = strdup(value);
         }
     }

     acl_xinetd_nv_pair *acl_xinetd_cfg_parser::nv_pair_new(const char *name, const char *value){
        acl_xinetd_nv_pair * pair = (acl_xinetd_nv_pair *) calloc(1, sizeof(acl_xinetd_nv_pair));
        if (pair == NULL)
            return (NULL);
#undef	ERETURN
#define	ERETURN(x) { \
	if (pair) { \
		if (pair->name) \
			free(pair->name); \
		if (pair->value) \
			free(pair->value); \
		free(pair); \
		pair = NULL; \
	} \
	return (x); \
}

        pair->name = strdup(name);
        if (pair->name == NULL){
            ERETURN (NULL);
        }

        pair->value = strdup(value);
        if (pair->value == NULL){
            ERETURN (NULL);
        }
        return pair;
    }
}

namespace oceanstar{
    int acl_xinetd_cfg_parser::xinetd_cfg_parse(char *line_nonl){
        if (*line_nonl == '\0')
            return (0);

        while (*line_nonl == ' ' || *line_nonl == '\t')  /* skip ' ' and '\t' */
            line_nonl++;
        if (*line_nonl == '#') /* comment line */
            return (0);

        char * ptr = line_nonl;
        char * ptr_eq = NULL;
        while (*ptr) {
            if (*ptr == '=') {
                *ptr = 0;  /* find the position of '=' */
                ptr_eq = ptr + 1; /* make ptr_eq pointer the next char addr*/
                break;
            }

            ptr++;
        }

        if (ptr_eq == NULL)
            return (0);

        ptr--;  /* move before '=' */
        while (ptr > line_nonl) {  /* delete any ' ' and '\t' before '=' */
            if (*ptr != ' ' && *ptr != '\t')
                break;
            *ptr-- = 0;
        }

        /* skip any ' ' and '\t' after '=' */
        while (*ptr_eq == ' ' || *ptr_eq == '\t')
            ptr_eq++;

        if (*ptr_eq == 0)
            return (0);

        ptr = ptr_eq;
        while (*ptr) {
            if (*ptr == '#') {
                *ptr = 0;
                break;
            }
            ptr++;
        }

        while (ptr > ptr_eq) {  /* delete any ' ' and '\t' */
            if (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
                break;
            *ptr-- = 0;
        }

        char *name = NULL, *value = NULL;
        name = line_nonl;
        value = ptr_eq;

        int index = -1;
        int size = nv_array.size();
        acl_xinetd_nv_pair *pair_search = NULL, * pair = NULL;
        for(int i = 0; i < size; i++){
            pair_search = nv_array[i];
            if(strcasecmp(name, pair_search->name) == 0){
                pair = pair_search;
                index = i;
            }
        }

        if (pair == NULL) { /* one new pair node */
            pair = nv_pair_new(name, value);
            if(pair == NULL){
                ERETURN(-1);
            }

            nv_array.emplace_back(pair);
        }else{
            nv_pair_update(nv_array[index], value);
        }
        return 0;
    }
}

namespace oceanstar{
    acl_xinetd_cfg_parser * acl_xinetd_cfg_load(const char *pathname){
            if (pathname == nullptr || *pathname == 0) {
                logger_error("input error");
                return nullptr;
            }

            char *content_buf = NULL;
            content_buf = acl_vstream_loadfile(pathname);
            if (content_buf == NULL) {
                logger_error("load file(%s) error(%s)", pathname, strerror(errno));
                return nullptr;
            }

#undef	RETURN
#define	RETURN(x) { \
	if (content_buf) \
		free(content_buf); \
	return (x); \
}

#undef	ERETURN
#define	ERETURN(x) { \
	if (content_buf) \
		free(content_buf); \
	if (xcp) { \
		acl_xinetd_cfg_free(xcp); \
	} \
	return (x); \
}

        acl_xinetd_cfg_parser *xcp = acl_xinetd_cfg_malloc();
        char *pline, *phead;
        phead = content_buf;
        while (1) {
            pline = acl_mystrline(&phead);
            if (pline == NULL) {
                break;
            }

            if(xcp->xinetd_cfg_parse(pline) < 0){
                ERETURN(NULL);
            }
        }

        RETURN(xcp) ;
    }
}

测试




#include <fcntl.h>
#include <stream/vstream.h>
#include <conf/acl_xinetd_cfg_parser.h>

using namespace oceanstar;

int main(int argc,char **argv){
    const char * pathname = "/home/oceanstar/CLionProjects/oceanstar_http/test/conf/tt2.cf";

    acl_xinetd_cfg_parser *cfg;

    cfg = acl_xinetd_cfg_load(pathname);
    if (cfg == NULL){
        printf("error=%s\r\n", strerror(errno));
        exit(1);
    }

    std::vector<acl_xinetd_nv_pair*>& nv_array = cfg->get_nv_array();
    for(auto iter : nv_array){
        printf("%s = %s\r\n", iter->name, iter->value);
    }

    acl_xinetd_cfg_free(cfg);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值