编程技巧
如果一个函数内有多个内存位置需要释放
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;
}