메뉴 건너뛰기


Developer > Application

C,C++ 환경(config) 파일 파서

2013.11.27 02:25

푸우 조회 수:13945


개발을 하다보면 외부에서 환경파일을 읽어 들여 사용하는 코드를 작성해야 할 경우가 많습니다.

그래서 환경파일을 읽어서 활용할 수 있도록 소스를 작성해 봤습니다.


다음은 처리 가능한 환경파일의 형태(양식)입니다.

# 행의 첫번째 글자가 #인 경우 그 행을 주석으로 간주합니다..

#==============================================================================
# 다음은 글로벌 변수입니다.
# 글로벌 변수는 다음에 정의되는 섹션 변수에서 재 정의하지 않으면 기본 값으로 사용하되는 변수 입니다.
# 변수명은 대소문자를 구별하지 않습니다.
# "변수명 = 변수값"과 같은 형태로 정의하고 = 앞뒤의 공백문자는 제거됩니다.
# 단, 값이 없는 경우는 "변수명"만 쓸 수 있습니다.
#==============================================================================
server=192.168.10.1
port = 8080

#==============================================================================
# 다음은 섹션 변수입니다. 다음의 예에서 섹션의 이름은 TEST1 이며 섹센은 섹션명을 [ ]로 묶어 정의해 줌으로써 
# 해당 섹션의 변수정의가 시작됩니다.
#==============================================================================
[TEST1]
server=192.168.10.100
port=8888
userid=scott
password=tiger 

#==============================================================================
# 다음은 TEST2 섹션 변수입니다.
# 변수를 정의할 때 값의 끝에 \을 사용하면 다음 줄에 연결하여 작성할 수 있습니다.
# 참고로 한라인은 1024바이트 내로 작성되어야 합니다.
# 만약 해의 마지막이 \로 끝나야 하는 값이라면 \\을 사용하여야 합니다.
# 변수 값 중에 New Line이 있다면 \n과 같이 사용해야 합니다.
#==============================================================================
[TEST2]
server=192.168.10.200
userid=admin
password=admin
desc=이 변수의 값은 굉장히 \n긴 변수 이므로 \
         여러줄에 걸쳐 작성\
          합니다. \\


첨부된 라이브러리를 활용하여 다음과 같이 프로그래밍할 수 있습니다.

 
#include <stdio.h>
#include "mirconf.h"

int main(int argc, char *argv[])
{
	MirConf *conf=NULL;
	int ret = 0, sectidx=MIRCONF_GLOBAL_SECT_NUM;
	unsigned char *value;

	ret = MirConfOpen(&conf, argv[1]);
	if(ret) {
		MirConfCheckErr(ret);
		return ret;
	}

	printf("총 %d개의 섹션이 정의되어 있습니다.\n", MirConfCnt(conf));
	
	printf("[Global] > server: %s\n", MirConfSearch(conf, sectidx, "server"));
	printf("[Global] > port: %s\n", MirConfSearch(conf, sectidx, "port"));

	// [TEST1] 섹션의 index를 알아낸다.
	sectidx = MirConfSectionSrch(conf, "TEST1");
	if(sectidx>0) {
		value = MirConfSearch(conf, sectidx, "server");
		printf("[TEST1] > server: %s\n", (value==NULL)?"Not Defined":value);
		value = MirConfSearch(conf, sectidx, "PORT");
		printf("[TEST1] > port: %s\n", (value==NULL)?"Not Defined":value);    // 대소문자 구별하지 않는다.
		value = MirConfSearch(conf, sectidx, "userid");
		printf("[TEST1] > userid: %s\n", (value==NULL)?"Not Defined":value);
		value = MirConfSearch(conf, sectidx, "password");
		printf("[TEST1] > password: %s\n", (value==NULL)?"Not Defined":value);
		value = MirConfSearch(conf, sectidx, "desc");
		printf("[TEST1] > desc: %s\n", (value==NULL)?"Not Defined":value);    // 글로벌 변수에도 정의하지 않았기에 NULL이 리턴된다.
	}

	// [TEST2] 섹션의 index를 알아낸다.
	sectidx = MirConfSectionSrch(conf, "TEST2");
	if(sectidx>0) {
		value = MirConfSearch(conf, sectidx, "server");
		printf("[TEST2] > server: %s\n", (value==NULL)?"Not Defined":value);
		value = MirConfSearch(conf, sectidx, "PORT");
		printf("[TEST2] > port: %s\n", (value==NULL)?"Not Defined":value);      // 글로벌 변수에서 정의한 값으로 대처된다. 
		value = MirConfSearch(conf, sectidx, "userid");
		printf("[TEST2] > userid: %s\n", (value==NULL)?"Not Defined":value);
		value = MirConfSearch(conf, sectidx, "password");
		printf("[TEST2] > password: %s\n", (value==NULL)?"Not Defined":value);
		value = MirConfSearch(conf, sectidx, "desc");
		printf("[TEST2] > desc: %s\n", (value==NULL)?"Not Defined":value);
	}

	MirConfClose(conf);

	return 0;
}


위 소스의 실행 결과는 다음과 같습니다.

총 2개의 섹션이 정의되어 있습니다.
[Global] > server: 192.168.10.1
[Global] > port: 8080
[TEST1] > server: 192.168.10.100
[TEST1] > port: 8888
[TEST1] > userid: scott
[TEST1] > password: tiger
[TEST1] > desc: Not Defined
[TEST2] > server: 192.168.10.200
[TEST2] > port: 8080
[TEST2] > userid: admin
[TEST2] > password: admin
[TEST2] > desc: 이 변수의 값은 굉장히
긴 변수 이므로 여러줄에 걸쳐 작성합니다. \


공개된 API는 다음과 같습니다.

// filename의 환경파일을 읽고 파싱한다.
// 정상적으로 처리한 경우 conf에 핸들을 저장하고 0을 리턴한다.
int MirConfOpen(MirConf **conf, unsigned char *filename);

// MirConfOpen()에서 생성한 핸들을 종료한다.
int MirConfClose(MirConf *conf);

// 지정된 section에서 특정 변수의 값을 알아낸다.
// 해당 변수의 값이 없는 경우는 NULL이 리턴된다.
unsigned char *MirConfSearch(MirConf *conf, int section_num, unsigned char *name);

// MirConfOpen()함수의 리턴값을 이용하여 에러메시지를 stderr에 출력한다.
void MirConfCheckErr(int ret);

// section 이름으로 섹션의 index번호를 알아낸다.
// section 번호가 0은 Global Section을 의미하며 section을 찾지 못한 경우는
// -1을 리턴한다.
int MirConfSectionSrch(MirConf *conf, unsigned char *section);

// 환경파일에 section이 총 몇개 정의되어 있는지 알아낸다.
int MirConfCnt(MirConf *conf);

 
Creative Commons License
Creative Commons License이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Copyright 조희창(Nicholas Jo). Some rights reserved. http://bbs.nicklib.com