c++解析配置文件

配置文件如下

listen              1935;
chunk_size          65000;
log_dir             ./objs/logs;
max_connections     2000;
vhost __defaultVhost__ {
    enabled         on;
    gop_cache       on;
    queue_length    30;
    forward         127.0.0.1:19350;
    hls {
        enabled         on;
        hls_path        ./objs/nginx/html;
        hls_fragment    5;
        hls_window      30;
    }
}

vhost aaa {
    enabled         on;
    gop_cache       on;
    queue_length    30;
    forward         127.0.0.1:19360;
    hls {
        enabled         on;
        hls_path        ./objs/nginx/html;
        hls_fragment    5;
        hls_window      30;
    }
     http_hooks {
        enabled         on;
        on_connect      http://127.0.0.1:8085/api/v1/clients;
        on_close        http://127.0.0.1:8085/api/v1/clients;
        on_publish      http://127.0.0.1:8085/api/v1/streams;
        on_unpublish    http://127.0.0.1:8085/api/v1/streams;
        on_play         http://127.0.0.1:8085/api/v1/sessions;
        on_stop         http://127.0.0.1:8085/api/v1/sessions;
    }
}

main.cpp


int main(int argc, char** argv){

	config->parse_options(argc,argv);
	
	return ret; 
}

config.hpp

#ifndef CONIFG_HPP
#define CONIFG_HPP

#include "core.hpp"
#include <vector>
#include <string>
#include "srs_core_reload.hpp"

//default vhost for rtmp

class SrsFileBuffer;

class SrsConfDirective{
public:
	int conf_line;
	std::string name;
	std::vector<std::string> args;
	std::vector<SrsConfDirective*> directives;
public:
	SrsConfDirective();
	virtual ~SrsConfDirective();
public:
	virtual int parse(const char* filename);
	
public:
	enum SrsDirectiveType{parse_file,parse_block};
	virtual int parse_conf(SrsFileBuffer* buffer,SrsDirectiveType type);
	virtual int read_token(SrsFileBuffer* buffer,std::vector<std::string>& args);
};

class SrsConfig
{
private:
	bool show_help;
	bool show_version;
	std::string config_file;
	SrsConfDirective* root;
	std::vector<ISrsReloadHandler*> subscribes;
public:
	SrsConfig();
	virtual ~SrsConfig();
public:
	virtual int reload();
	virtual void subscribe(ISrsReloadHandler* handler);
	virtual void unsubsribe(ISrsReloadHandler* handler);
public:
	virtual int parse_options(int argc,char** argv);
	virtual void printtree(SrsConfDirective *root);
private:
	virtual int parse_file();
	virtual int parse_argv(int& i,char** argv);
	virtual void print_help(char** argv);
};

bool srs_dective_equals(SrsConfDirective* a,SrsConfDirective* b);

extern SrsConfig *config;

#endif


config.cpp

#include "srs_core_config.hpp"
#include "srs_core_error.hpp"
#include "srs_core_log.hpp"
#include "srs_core.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
// file operations.
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>

#include <vector>
#include <algorithm>
using namespace std;

#define FILE_OFFSET(fd) lseek(fd,0,SEEK_CUR)

int64_t FILE_SIZE(int fd)
{
	int64_t pre = FILE_OFFSET(fd);
	int64_t pos = lseek(fd,0,SEEK_END);
	lseek(fd,pre,SEEK_SET);
	return pos;
}

#define LF (char)0x0a
#define CR (char)0x0d

bool is_common_space(char ch)
{
	return (ch==' '||ch=='\t'||ch==CR||ch==LF);
}

class SrsFileBuffer
{
private:
	// last available position
	char* last;
	// end of buffer
	char* end;
	// start of buffer
	char* start;
public:
	//current consumed position.
	char* pos;
	//current parsed line.
	int line;
	
	SrsFileBuffer();
	virtual ~SrsFileBuffer();
	virtual int fullfill(const char* filename);
	virtual bool empty();
};

SrsFileBuffer::SrsFileBuffer()
{
	line = 0;
	pos = last = start = NULL;
	end = start;
}

SrsFileBuffer::~SrsFileBuffer()
{
	srs_freepa(start);
}

int SrsFileBuffer::fullfill(const char* filename)
{	
	int ret = ERROR_SUCCESS;
	int fd = -1;
	int nread = 0;
	int filesize = 0;
	
	if((fd=::open(filename,O_RDONLY,0))<0){
		ret = ERROR_SYSTEM_CONFIG_INVALID;
		srs_error("open conf file error. ret=%d", ret);
		goto finish;
	}
	
	if((filesize = FILE_SIZE(fd)-FILE_OFFSET(fd))<=0){
		ret = ERROR_SYSTEM_CONFIG_EOF;
		srs_error("read conf file error. ret=%d", ret);
		goto finish;
	}
	
	srs_freepa(start);
	pos = last = start = new char[filesize];
	end = start + filesize;
	
	if((nread = read(fd, start, filesize)) !=  filesize)
	{
		ret = ERROR_SYSTEM_CONFIG_INVALID;
		srs_error("read file read error. expect %d, actual %d bytes,ret=%d",filesize, nread,ret);
		goto finish;
	}
	
finish:
	if(fd>0){
		::close(fd);
	}
	return ret;
	
}

bool SrsFileBuffer::empty(){
	return pos >= end;
}

SrsConfDirective::SrsConfDirective()
{
}

SrsConfDirective::~SrsConfDirective()
{	
	std::vector<SrsConfDirective*>::iterator it;
	for(it = directives.begin();it!=directives.end();++it){
		SrsConfDirective* directive = * it;
		srs_freep(directive);		
	}
	directives.clear();
}

void SrsConfig::printtree(SrsConfDirective *root){
	std::vector<SrsConfDirective*>::iterator it;
	std::vector<std::string>::iterator subit;
	cout << "name: "<< root->name << " value:";
	for(subit=root->args.begin();subit!=root->args.end();++subit){
		cout << " " <<*subit <<" ";
	}
	cout << endl;
	if(!root->directives.empty()){
		cout << "======" << root->name <<" sub  =======" <<endl;
		for(it = root->directives.begin();it!=root->directives.end();++it){
			SrsConfDirective* directive = *it;
			printtree(directive);	
		}
		cout << "======" << root->name <<" sub end  =======" <<endl;
	}
}

int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type)
{
	int ret = ERROR_SUCCESS;
	while(true){
		std::vector<string> args;
		ret = read_token(buffer,args);
		
		/**
			ret maybe:
			ERROR_SYSTEM_CONFIG_INVALID		error
			ERROR_SYSTEM_CONFIG_DIRECTIVE	directive terminated by ';' found
			ERROR_SYSTEM_CONFIG_BLOCK_START	toket terminated by '{' found
			ERROR_SYSTEM_CONFIG_BLOCK_END 	the '}'	found
			ERROR_SYSTEM_CONFIG_EOF			the config file is done
		*/
		if(ret == ERROR_SYSTEM_CONFIG_INVALID){
			return ret;
		}
		if(ret == ERROR_SYSTEM_CONFIG_BLOCK_END){
			if(type!=parse_block){
				srs_error("line %d: unexpected \"}\"",buffer->line);
				return ret;
			}
			return ERROR_SUCCESS;
		}
		if(ret == ERROR_SYSTEM_CONFIG_EOF){
			if(type == parse_block){
				//srs_error("line %d : unexpected end of file, expecting\"}\"",buffer->line);
				return ret;
			}
			return ERROR_SUCCESS;
		}
		
		if(args.empty()){
			srs_error("line %d: empty directive.",buffer->line);
			return ret;
		}	
		
		SrsConfDirective* directive = new SrsConfDirective();
		directive->conf_line = buffer->line;
		directive->name = args[0];
		args.erase(args.begin());
		directive->args.swap(args);
		
		directives.push_back(directive);
		if(ret == ERROR_SYSTEM_CONFIG_BLOCK_START){
			if((ret=directive->parse_conf(buffer,parse_block))!=ERROR_SUCCESS){
				return ret;
			}
		}
	}
	return ret;
}

int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<string>& args)
{
	int ret = ERROR_SUCCESS;
	char* pstart = buffer->pos;
	int startline = buffer->line;
	bool sharp_comment = false;
	bool d_quoted = false;
	bool s_quoted = false;
	bool need_space = false;
	bool last_space = true;
	while(true){
		if(buffer->empty()){
			ret = ERROR_SYSTEM_CONFIG_EOF;
			
			if(!args.empty() || !last_space){
				srs_error("line %d: unexpected end of file,expecting; or \"}\"",buffer->line);
				return ERROR_SYSTEM_CONFIG_INVALID;
			}
			//srs_error("end of file. ret=%d",ret);
			return ret;
		}
		char ch = *buffer->pos++;
		if(ch == LF){
			buffer->line++;
			sharp_comment = false;
		}
		
		if(sharp_comment){
			continue;
		}
		
		if(need_space){
			if(is_common_space(ch)){
				last_space = true;
				need_space = false;
				continue;
			}
			if(ch==';'){
				return ERROR_SYSTEM_CONFIG_DIRECTIVE;
			}
			if(ch=='{'){
				return ERROR_SYSTEM_CONFIG_BLOCK_START;
			}
			srs_error("line %d: unexpected '%c'", buffer->line,ch);
			return ERROR_SYSTEM_CONFIG_INVALID;
		}
		
		// last charecter is space
		if(last_space){
			if(is_common_space(ch)){
				continue;
			}
			pstart = buffer->pos - 1;
			startline = buffer->line;
			switch(ch){
				case ';':
					if(args.size()==0){
						srs_error("line %d: unexpected ';'",buffer->line);
						return ERROR_SYSTEM_CONFIG_INVALID;
					}
					return ERROR_SYSTEM_CONFIG_DIRECTIVE;
				case '{':
					if(args.size()==0){
						srs_error("line %d: unexpected '{'",buffer->line);
						return ERROR_SYSTEM_CONFIG_INVALID;
					}
					return ERROR_SYSTEM_CONFIG_BLOCK_START;
				case '}':
					if(args.size()!=0){
						srs_error("line %d :unexpected '}'",buffer->line);
						return ERROR_SYSTEM_CONFIG_INVALID;
					}
				case '#':
					sharp_comment = 1;
					continue;
				case '"':
					pstart++;
					d_quoted = true;
					last_space = 0;
					continue;
				case '\'':
					pstart++;
					s_quoted = true;
					last_space = 0;
					continue;
				default:
					last_space = 0;
					continue;
			}
		} else {
			bool found  = false;
			if(d_quoted){
				if(ch=='"'){
					d_quoted = false;
					need_space = true;
					found = true;
				}
			} else if(s_quoted) {
				if(ch == '\''){
					s_quoted = false;
					need_space = true;
					found = true;
				}
			} else if(is_common_space(ch) || ch==';' || ch=='{'){
				last_space = true;
				found = 1;
			}
			
			if(found){
				int len = buffer->pos - pstart;
				char* word  = new char[len];
				memcpy(word,pstart,len);
				word[len-1]=0;
				
				string word_str = word;
				if(!word_str.empty()){
					args.push_back(word_str);
				}
				srs_freepa(word);
				
				if(ch==';'){
					return ERROR_SYSTEM_CONFIG_DIRECTIVE;
				}
				if(ch=='{'){
					return ERROR_SYSTEM_CONFIG_BLOCK_START;
				}
			}
		}
		
	}
	
	return ret;
}

int SrsConfDirective::parse(const char* filename)
{
	int ret = ERROR_SUCCESS;
	SrsFileBuffer buffer;
	if((ret=buffer.fullfill(filename))!=ERROR_SUCCESS){
		return ret;
	}
	return parse_conf(&buffer,parse_file);
}

SrsConfig* config = new SrsConfig();

SrsConfig::SrsConfig()
{
	show_help = false;
	show_version = false;
	root = new SrsConfDirective();
	root->conf_line = 0;
	root->name = "root";
}

SrsConfig::~SrsConfig()
{
	//SrsConfig::printtree(root);
	delete root;
}

int SrsConfig::parse_options(int argc,char** argv)
{
	int ret = ERROR_SUCCESS;
	for(int i=1;i<argc;i++){
		if((ret=parse_argv(i,argv))!=ERROR_SUCCESS){
			return ret;
		}
	}
	
	if(show_help){
		print_help(argv);
	}
	
	if(show_version){
		printf("%s\n",RTMP_SIG_SRS_VERSION);
	}
	
	if(show_help || show_version){
		exit(0);
	}
	
	return parse_file();
}

int SrsConfig::parse_file()
{
	int ret = ERROR_SUCCESS;
	if(config_file.empty()){ 
		//return ERROR_SYSTEM_CONFIG_INVALID;
	}
	if(config_file.empty()){
		return ERROR_SYSTEM_CONFIG_INVALID;
	}
	config_file = CONFIG_DIRECTORY + config_file;
	//cout << config_file << endl;
	if((ret=root->parse(config_file.c_str()))!=ERROR_SUCCESS){
		return ret;
	}
	return ret;
}

void SrsConfig::print_help(char** argv){
	printf(RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION
		" Copyright (c) 2013 winlin\n"
		"Contributors: "RTMP_SIG_SRS_CONTRIBUTOR"\n"
		"Build: "SRS_BUILD_DATE" Configuration: "SRS_CONFIGURE"\n"
		"Usage: %s [-h?Vv] [-c <filename>]\n"
		"\n"
		"Options:\n"
		" 	-?-h			: show help\n"
		" 	-v-V			: show version and exit\n"
		"	-c filename		: set configuration file\n"
		"\n",
		argv[0]);
}

int SrsConfig::parse_argv(int& i, char** argv){
	int ret = ERROR_SUCCESS;
	char* p = argv[i];
	if(p==NULL)
		return ERROR_SYSTEM_CONFIG_INVALID;
	if(*p++!='-'){
		ret = ERROR_SYSTEM_CONFIG_INVALID;
		srs_error("invalid options(index=%d,value=%s), must start with - ,see help:%s -h,ret=%d",i,argv[i],argv[0],ret );
		return ret;
	}
	
	while(*p){
		switch(*p++){
			case '?':
			case 'h':
				show_help = true;
				break;
			case 'v':
			case 'V':
				show_version = true;
				break;
			case 'c':
				if(*p){
					config_file = p;
					return ret;
				}
				if(argv[++i]){
					config_file = argv[i];
					return ret;
				}
				ret = ERROR_SYSTEM_CONFIG_INVALID;
				srs_error("option \"-c\" requires parameter ,ret=%d",ret);
				return ret;
			default:
				ret = ERROR_SYSTEM_CONFIG_INVALID;
				srs_error("invalid option:\"%c\", see help: %s -h,ret=%d",*(p-1),argv[0],ret);
				return ret;
		}
	}
	
	return ret;
}

void SrsConfig::subscribe(ISrsReloadHandler* handler)
{
}

void SrsConfig::unsubsribe(ISrsReloadHandler* handler)
{
}

int SrsConfig::reload()
{	
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
c ini配置文件读写是一种常见的配置文件读写方式。在C语言中,通常使用文件操作函数来读写ini配置文件。 读取ini文件首先需要打开文件,可以使用fopen函数打开文件,并指定打开方式为"r"(只读方式)。然后逐行读取文件内容,可以使用fgets函数逐行读取。读取到的每一行字符串都可以通过字符串处理函数进行进一步操作,例如使用strtok函数将行字符串分割成键值对。 对于每一行的键值对,可以进一步使用字符串处理函数进行解析。可以使用strchr函数找到等号(=)的位置,将键和值分隔开。然后可以使用strcpy或strncpy函数将键和值分别复制到变量中,并进行相应的后续处理。 写入ini文件也需要打开文件,可以使用fopen函数打开文件,并指定打开方式为"w"(写入方式)。然后可以使用fprintf函数将配置项写入文件。具体的操作是先写入键的字符串,然后写入等号(=),最后写入值的字符串。写入完毕后,可以使用fclose函数关闭文件。 需要注意的是,在读取和写入ini文件时,需要进行错误处理,例如检查文件是否打开成功、是否成功读写、文件关闭时是否出错等。这样可以保证程序的健壮性。 总之,对于C语言来说,ini配置文件读写是一种比较简单和常见的操作,通过使用文件操作函数和字符串处理函数,可以方便地读取和写入ini文件中的配置项。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值