/** @file strparsing.c @date 2009-06-01 @author 장길석 jwjwmx@gmail.com @brief Ver 0.0.4 문자열을 분석하여 tstrlist로 생성한다. @todo @bug @remark @warning - 저작권 에프에이리눅스(주) - 외부공개 금지 @section ModifyInfo 수정 정보 - 2009-07-06 -# Doxygen을 위한 주석 수정 - 2009-06-01 -# 기본 기능을 추가 */ //------------------------------------------------------------------------------ #include #include #include #include #include #include #include #define MAX_BUFFSIZE 1024 #define MAX_IDENTIFY 128 int strp_error_code; // 에러코드 static char buff_parse[1024]; static char buff_identify[1024]; static char *read_string( tstrlist *strplist, char *str_identify) //설명: 구별자의 문자열 데이터를 구한다. //인수: tstrlist *strplist : tstrlist 객체 포인터 // char *str_identify : 구별자 문자열 //반환: 섹션과 구별자의 문자열 데이터 //주의: 섹션과 구별자가 없다면 NULL을 반환 // 반환된 문자열 포인터로 메모리 소멸을 해서는 안 된다. { int index; index = tstrlist_indexof( strplist, str_identify); if ( 0 > index) return NULL; return (char *)tstrlist_get_object( strplist, index); } static char *get_inner( char *str, char branch) // 설명: " 또는 ' 으로 묶인 문자열 값을 구한다. // 참고: 인용 부호 안에는 공백 문자 이상의 모든 문자를 포함한다. // 반환: 인수로 받은 문자열 포인터에서 다음 처리할 문자 위치 { char *pbuff; // 버퍼 사용을 위한 포인터 char ch_data; // 검색 대상 문자 pbuff = buff_parse; while( '\0' != *str) { ch_data = *str++; if ( branch == ch_data) // 구별자 문자를 만났다면 { break; // break } else { *pbuff++ = ch_data; // 문자열 복사 } } *pbuff = '\0'; // 데이터 구성 완료 return str; } static char *get_string( char *str) // 설명: 문자열 끝이나 '=' 문자를 만나기 까지 공백없는 문자열을 구한다. // 반환: 인수로 받은 문자열 포인터에서 다음 처리할 문자 위치 { char *pbuff; // 버퍼 사용을 위한 포인터 char ch_data; // 검색 대상 문자 pbuff = buff_parse; while( '\0' != *str) { ch_data = *str; if ( ( ' ' == ch_data) || ( '=' == ch_data)) { break; } else { *pbuff++ = ch_data; } str++; // 이 함수 호출 후에 '='문자가 있는지를 확인해야 하므로, 여기서 포인터 증가 } *pbuff = '\0'; return str; } static char *get_parse( char *str) // 설명: 인수로 받은 문자열을 인용부호와 인용부호가 없는 문자열에 따라 파싱한다. // 반환: 인수로 받은 문자열 포인터에서 다음 처리할 문자 위치 { buff_parse[0] = '\0'; while( '\0' != *str) { switch( *str++) { case '\'' : // 인용부호 ' 문자 사이의 문자열을 구한다. { str = get_inner( str, '\''); return str; } case '"' : // 인용부호 " 문자 사이의 문자열을 구한다. { str = get_inner( str, '\"'); return str; } case ' ' : // 공백이나 case '=' : // 분리자 이면 다음 문자를 계속 검색 break; default : { str = get_string( str-1); // 공백이나 분리자를 만날 때까지의 문자열을 구한다. return str; } } } return str; } static int is_identify( char *str) // 설명: 방금 구한 문자열이 구별자인지를 확인한다. // 참고: 문자열 뒤에 공백이나 분리자만 있다면 구별자로 인정 // 반환: 구별자 여부 { while( '\0' != *str) { switch( *str++) { case ' ' : break; // 공백 문자이면 다음 문자를 계속 검색 case '=' : return 1; // '=' 문자가 있으면 OK default : return 0; // 공백이나 '=' 문자가 아니면 FALSE } } return 0; } static void parse_string( tstrlist *lst_parse, char *str) // 설명: 구별자와 구별자에 대한 데이터를 구한다. // 반환: 구별자 개수 { char *pdata; while ( '\0' != *str) { str = get_parse( str); if ( '\0' == buff_parse[0]) { break; } if ( !is_identify( str)) { continue; } memcpy( buff_identify, buff_parse, strlen( buff_parse)+1); // NULL까지 포함하기 위해 +1 str = get_parse( str); pdata = ( char *)malloc( strlen( buff_parse)+1); if ( NULL == pdata) { strp_error_code = STRPERR_OUT_OF_MEMORY; break; } else { memcpy( pdata, buff_parse, strlen( buff_parse)+1); // NULL까지 포함하기 위해 +1 tstrlist_add_object( lst_parse, buff_identify, pdata); } } } int strp_read_bool( tstrlist *strplist, char *str_identify, int default_value) /** @brief 구별자가 지정하는 Boolean 데이터를 구한다. @param strplist : 파싱 자료를 가지고 있는 tstlist @param str_identify : 구별자 문자열 @param default_value : 값이 없다면 대신 반환될 기본값 @warning 구별자의 문자열이 0 이면 FALSE로 반환하며\n 이외는 무조건 TRUE로 반환한다.\n 즉, 구별자가 가지고 있는 문자열 정보가\n '0' 인지 아닌지의 여부를 반환한다. */ { char *data; int int_data; data = read_string( strplist, str_identify); // 먼저 구별자로 데이터를 구한다. if ( NULL == data) return default_value; // 찾는 데이터가 없다면 기본값을 반환한다. else if ( 0 == strlen( data) ) return default_value; // 문자열 데이터가 없다면 기본값을 반환한다. else if ( 0 == sscanf( data, "%d", &int_data)) return default_value; // 정수로 변환된 값이 없다면 기본값을 반환 else return 0 != int_data; // 정수 값이 0이면 FALSE로 반환한다. } double strp_read_real( tstrlist *strplist, char *str_identify, double default_value) /** @brief 구별자가 지정하는 정수 데이터를 구한다. @param strplist : 파싱 자료를 가지고 있는 tstlist @param str_identify : 구별자 문자열 @param default_value : 값이 없다면 대신 반환될 기본값 @return - 구별자에 해당하는 실수 값 - 저정한 섹션이나 구별자에 대한 실수 값이 없다면 기본값을 반환 */ { char *data; double float_data; data = read_string( strplist, str_identify); // 먼저 구별자로 데이터를 구한다. if ( NULL == data) return default_value; // 찾는 데이터가 없다면 기본값을 반환한다. else if ( 0 == strlen( data) ) return default_value; // 문자열 데이터가 없다면 기본값을 반환한다. else if ( 0 == sscanf( data, "%lf", &float_data)) return default_value; // 실수로 변환된 값이 없다면 기본값을 반환 else return float_data; // 실수 값을 반환한다. } int strp_read_integer( tstrlist *strplist, char *str_identify, int default_value) /** @brief 구별자가 지정하는 정수 데이터를 구한다. @param strplist : 파싱 자료를 가지고 있는 tstlist @param str_identify : 구별자 문자열 @param default_value : 값이 없다면 대신 반환될 기본값 @return - 구별자에 해당하는 정수 값 - 저정한 섹션이나 구별자에 대한 정수 값이 없다면 기본값을 반환 */ { char *data; int int_data; data = read_string( strplist, str_identify); // 먼저 구별자로 데이터를 구한다. if ( NULL == data) return default_value; // 찾아진 데이터가 없다면 기본값을 반환한다. else if ( 0 == strlen( data) ) return default_value; // 문자열 데이터가 없다면 기본값을 반환한다. else if ( 0 == sscanf( data, "%d", &int_data)) return default_value; // 정수로 변환된 값이 없다면 기본값을 반환 else return int_data; // 정수값을 반환한다. } char *strp_read_string( tstrlist *strplist, char *str_identify, char *default_value) /** @brief 섹션과 구별자가 지정하는 문자열 데이터를 구한다. @param strplist : 파싱 자료를 가지고 있는 tstlist @param str_identify : 구별자 문자열 @param default_value : 값이 없다면 대신 반환될 기본값 @return\n 구별자의 문자열 정보\n 저정한 섹션이나 구별자에 대한 문자열이 없다면 기본값을 반환 @warning 절대 반환 받은 문자열을 소멸 시켜서는 안 된다!! */ { char *data; data = read_string( strplist, str_identify); // 먼저 구별자로 데이터를 구한다. if ( NULL == data) return default_value; // 찾아진 데이터가 없다면 기본값을 반환한다. else if ( 0 == strlen( data) ) return default_value; // 문자열 데이터가 없다면 기본값을 반환한다. else return data; } char *strp_error_string( void) /** @brief strp_error_code에 대한 에러 설명 문자열을 반환 @return 에러 코드에 대한 에러 설명 문자열 포인터 @warning 절대 반환 받은 문자열을 소멸 시켜서는 안 된다!! */ { char *error_string[] ={ "에러 없음", // INIERR_NONE "메모리 부족", // INIERR_OUT_OF_MEMORY "파일 이름 지정 오류", // INIERR_FILENAME_FAIL "자료 없음", // INIERR_NO_DATA "IniFile 없음", // INIERR_NO_FILE "IniFile을 읽을 수 없음", // INIERR_ACCESS_FAIL "섹션 리스트 생성 실패", // INIERR_CREATE_SECTION_FAIL "구별자 생성 실패", // INIERR_CREATE_IDENTIFY_FAIL "인수의 객체가 NULL" // INIERR_NULL_POINTER }; return( error_string[strp_error_code]); } int strp_print_error( char *remark) /** @brief ini_error_code에 대한 에러 설명 문자열을 화면에 출력 @param remark : 에러 설명 문자열 끝에 첨부하여 출력할 문자열 @return\n 에러 코드 */ { printf( "[str parsing error:%d]%s %s\n", strp_error_code, strp_error_string(), remark); return strp_error_code; } void strp_free( tstrlist *strplist) /** @brief strparsing 객체를 소멸한다. @param strplist : strparsing 객체 */ { int ndx; char *pdata; for ( ndx = 0; ndx < tstrlist_getcount( strplist); ndx++) { pdata = ( char *)tstrlist_get_object( strplist, ndx); // 객체로 등록한 문자열 제거 free( pdata); } tstrlist_free( strplist); // 리스트 소멸 } tstrlist *strp_parsing( char *data) /** @brief data 문자열을 분석해서 구별자와 데이터로 구성된 아이템 목록을 만든다.\n @param data : 문자열 데이터 @return\n 구별자와 데이터로 구성된 아이템의 tstrlist *\n 읽기에 실패했다면 NULL을 반환 */ { tstrlist *lst_parse; strp_error_code = STRPERR_NONE; // 에러코드: 에러 없음 lst_parse = tstrlist_create(); // tstrlist 객체 생성 if ( NULL == lst_parse) // tstrlist 객체를 생성하지 못했다면 { strp_error_code = STRPERR_CREATE_LIST_FAIL; // 에러코드: 루트 섹션 리스트 생성 return NULL; } parse_string( lst_parse, data); return lst_parse; }