/** @file tstrlist.c @date 2009/1/14 @author 오재경 freefrug@falinux.com FALinux.Co.,Ltd. @brief Ver 0.9.1 Delphi 형식의 스트링리스트 객체이다. tlist.c 에서 구현한 tlist 를 상속(?) 받아 사용한다. @modify @todo @bug @remark 함수 테스트 필요 (테스트 완료표시 ">>") >>tstrlist_create >>tstrlist_free >>tstrlist_clear >>tstrlist_add >>tstrlist_add_object >>tstrlist_delete >>tstrlist_get_string >>tstrlist_get_object >>tstrlist_get_tag tstrlist_exchange >>tstrlist_indexof tstrlist_insert >>tstrlist_first >>tstrlist_last tstrlist_move >>tstrlist_put_string >>tstrlist_put_tag >>tstrlist_remove tstrlist_pack >>tstrlist_getcount >>tstrlist_sort >>tstrlist_commatext >>tstrlist_load_from_file >>tstrlist_save_to_file @warning */ // // 저작권 에프에이리눅스(주) // 외부공개 금지 // //---------------------------------------------------------------------------- #define EMBEDDED_LINUX // 이렇게 처리하지 않으면 EClipse에서 C 영역이 회색 바탕이 됨 #ifdef MS_WIN32 #undef EMBEDDED_LINUX #endif #include #include #include #include #include #include #include #ifdef EMBEDDED_LINUX #include #endif char desc_tstrlist[] = "falinux tstrlist ver 0.9.0"; /// @{ /// @brief local 함수리스트 static int tstrlist_calcu_strcap( const char *str ); /// 할당할 문자열의 공간을 계산한다. static tstritem *tstrlist_newitem( const char *str ); /// 새로운 문자열 아이템을 생성한다. static tstritem *tstrlist_replace_itemstr( tstritem *sitem, const char *str ); /// 문자열 아이템의 문자열을 변경한다. static int tstrlist_sortfunc( const void *ppa, const void *ppb ); /// 문자열 정렬을 위해 크기를 비교한다. /// @} static void trim( char *str) // 설명: 인수로 받은 문자열에서 앞과 뒤의 공백 문자를 제거한다. { int sz_str; int ndx; sz_str = strlen( str); for( ndx = sz_str; 0 <= ndx; ndx--) // 문자열 뒤의 화이트 문자를 제거 { if ( ' ' != str[ndx]) break; // 한글이 있을 경우를 생각해서 ' ' 문자를 직접 비교한다. str[ndx] = '\0'; } sz_str = strlen( str); // 문자열 앞의 화이트 문자를 제거 for( ndx = 0; ndx < sz_str; ndx++) { if ( ' ' != str[ndx]) // 한글이 있을 경우를 생각해서 ' ' 문자를 직접 비교한다. break; } memcpy( str, str+ndx, strlen( str)); // 회이트 문자가 아닌 부분을 포인터의 시작 위치로 이동 } //------------------------------------------------------------------------------ /** @brief 문자열에서 앞뒤의 특수문자와 공백문자를 제거한다. @param line 문자열 포인터 *///---------------------------------------------------------------------------- static void __trimstr( char *line ) { int idx, len; // 뒷쪽 공백문자와 특수문자 제거 len = strlen(line); for( idx=len-1; idx>=0; idx-- ) { if ( line[idx] > ' ' ) break; } line[idx+1] = '\0'; // 앞쪽 공백문자와 특수문자 제거 len = strlen(line); for( idx=0; idx ' ' ) break; } if ( (0 < idx) && (idx < len) ) { memmove( line, line + idx, len-idx+1 ); } } //------------------------------------------------------------------------------ /** @brief 할당할 문자열의 공간을 계산한다. @param str 추가되는 문자열 포인터 @return 할당할 문자열의 개수 @remark 최소 MIN_STR_LEN 바이트이상이며 2의 배수로 증가한다. *///---------------------------------------------------------------------------- static int tstrlist_calcu_strcap( const char *str ) { int slen, square; slen = strlen( str ); square = 0; while( slen ) { slen = slen >> 1; square ++; } slen = 1 << square; if ( slen < MIN_STR_LEN ) slen = MIN_STR_LEN; return slen; } //------------------------------------------------------------------------------ /** @brief 새로운 문자열 아이템을 생성한다. @param str 추가되는 문자열 포인터 @return 생성된 문자열 아이템 구조체 포인터 *///---------------------------------------------------------------------------- static tstritem *tstrlist_newitem( const char *str ) { tstritem *sitem; int cap; cap = tstrlist_calcu_strcap( str ); sitem = (tstritem *)malloc( sizeof(tstritem) + cap ); sitem->fstrcap = cap; sitem->fstr = (char *)sitem + sizeof(tstritem); sitem->ftag = 0; strncpy( sitem->fstr, str, cap ); return sitem; } //------------------------------------------------------------------------------ /** @brief 문자열 아이템의 문자열을 변경한다. @param sitem 문자열 아이템 구조체의 포인터 @param str 변경되는 문자열 포인터 @return 변경된 아이템구조체 포인터 *///---------------------------------------------------------------------------- static tstritem *tstrlist_replace_itemstr( tstritem *sitem, const char *str ) { int cap; cap = sitem->fstrcap; if ( (int)strlen(str) > sitem->fstrcap ) { tstritem *newitem; newitem = tstrlist_newitem( str ); newitem->ftag = sitem->ftag; newitem->fdata = sitem->fdata; free( sitem ); return newitem; } else { strncpy( sitem->fstr, str, cap ); return sitem; } } //------------------------------------------------------------------------------ /** @brief tstrlist 객체를 생성한다. @return 객체의 포인터 *///---------------------------------------------------------------------------- tstrlist* tstrlist_create ( void ) { tstrlist *that; that = ( tstrlist *) malloc( sizeof( tstrlist ) ); that->ftlst = tlist_create(); return that; } //------------------------------------------------------------------------------ /** @brief tstrlist 객체를 소멸시킨다. @param *that 관리 객체의 포인터 *///---------------------------------------------------------------------------- void tstrlist_free ( tstrlist *that ) { tstrlist_clear( that ); tlist_free( that->ftlst ); free( that ); } //------------------------------------------------------------------------------ /** @brief 모든 아이템을 제거한다. @param that 관리 객체의 포인터 *///---------------------------------------------------------------------------- void tstrlist_clear ( tstrlist *that ) { int loop; void *ptr; tlist *tlst = that->ftlst; // 문자열 객체를 해제한다. for (loop=0; loopfcount; loop++) { ptr = tlist_get( tlst, loop ); if (ptr) free( ptr ); } tlist_clear( tlst ); } //------------------------------------------------------------------------------ /** @brief 문자열 아이템을 추가한다. @param that 관리 객체의 포인터 @param str 새로이 추가되는 문자열 포인터 @return 추가된 아이템의 인덱스 *///---------------------------------------------------------------------------- int tstrlist_add ( tstrlist *that, const char *str ) { tlist *tlst = that->ftlst; tstritem *sitem; int result; sitem = tstrlist_newitem( str ); // 문자열 객체 생성 result = tlist_add( tlst, sitem ); return result; } //------------------------------------------------------------------------------ /** @brief 문자열과 사용자 포인터를 추가한다. @param that 관리 객체의 포인터 @param str 새로이 추가되는 문자열 포인터 @param pdata 사용자 포인터 @return 추가된 아이템의 인덱스 *///---------------------------------------------------------------------------- int tstrlist_add_object ( tstrlist *that, const char *str, void *obj ) { tlist *tlst = that->ftlst; tstritem *sitem; int result; result = tstrlist_add( that, str ); sitem = (tstritem *)tlist_get( tlst, result ); sitem->fdata = obj; return result; } //------------------------------------------------------------------------------ /** @brief 하나의 아이템을 제거한다. @param that 관리 객체의 포인터 @param index 제거될 아이템의 인덱스 *///---------------------------------------------------------------------------- void tstrlist_delete ( tstrlist *that, int index ) { tlist *tlst = that->ftlst; tstritem *sitem; sitem = (tstritem *)tlist_get( tlst, index ); if (sitem) { free( sitem ); } tlist_delete( tlst, index ); } //------------------------------------------------------------------------------ /** @brief 인덱스에 해당하는 문자열 포인터를 반환한다. @param that 관리 객체의 포인터 @param index 아이템 인덱스 @return 인덱스에 해당하는 문자열 포인터 *///---------------------------------------------------------------------------- char *tstrlist_get_string ( tstrlist *that, int index ) { tlist *tlst = that->ftlst; tstritem *sitem; sitem = (tstritem *)tlist_get( tlst, index ); if (sitem) { return sitem->fstr; } return NULL; } //------------------------------------------------------------------------------ /** @brief 인덱스에 해당하는 사용자 포인터를 반환한다. @param that 관리 객체의 포인터 @param index 아이템 인덱스 @return 인덱스에 해당하는 사용자 포인터 *///---------------------------------------------------------------------------- void *tstrlist_get_object ( tstrlist *that, int index ) { tlist *tlst = that->ftlst; tstritem *sitem; sitem = (tstritem *)tlist_get( tlst, index ); if (sitem) { return sitem->fdata; } return NULL; } //------------------------------------------------------------------------------ /** @brief 인덱스에 해당하는 정수형 태그변수를 반환한다. @param that 관리 객체의 포인터 @param index 아이템 인덱스 @return 인덱스에 해당하는 정수형 태그변수 *///---------------------------------------------------------------------------- int tstrlist_get_tag ( tstrlist *that, int index ) { tlist *tlst = that->ftlst; tstritem *sitem; sitem = (tstritem *)tlist_get( tlst, index ); if (sitem) { return sitem->ftag; } return -1; } //------------------------------------------------------------------------------ /** @brief 2개의 아이템 위치를 교환한다. @param that 관리 객체의 포인터 @param index1 교환할 인덱스1 @param index2 교환할 인덱스2 *///---------------------------------------------------------------------------- void tstrlist_exchange ( tstrlist *that, int index1, int index2 ) { tlist *tlst = that->ftlst; tlist_exchange( tlst, index1, index2 ); } //------------------------------------------------------------------------------ /** @brief 문자열이 동일한 인덱스를 구한다. @param that 관리 객체의 포인터 @param str 비교 문자열 포인터 @return 문자열이 해당되는 인덱스, 존재하지 않으면 -1 *///---------------------------------------------------------------------------- int tstrlist_indexof ( tstrlist *that, const char *str ) { tlist *tlst = that->ftlst; tstritem *sitem; int loop; for (loop=0; loopfcount; loop++) { sitem = (tstritem *)tlist_get( tlst, loop ); if ( 0 == strcmp( sitem->fstr, str ) ) { return loop; } } return -1; } //------------------------------------------------------------------------------ /** @brief 아이템을 특정 위치에 추가한다. @param that 관리 객체의 포인터 @param index 추가할 아이템가 들어갈 인덱스 @param str 추가할 문자열 포인터 *///---------------------------------------------------------------------------- void tstrlist_insert ( tstrlist *that, int index, char *str ) { tlist *tlst = that->ftlst; tstritem *sitem; sitem = tstrlist_newitem( str ); // 문자열 객체 생성 tlist_insert( tlst, index, sitem ); } //------------------------------------------------------------------------------ /** @brief 첫번째 문자열 포인터를 돌려준다. @param that 관리 객체의 포인터 @return 첫번째 문자열 포인터 *///---------------------------------------------------------------------------- char *tstrlist_first ( tstrlist *that ) { return tstrlist_get_string( that, 0 ); } //------------------------------------------------------------------------------ /** @brief 마지막 문자열 포인터를 구한다. @param that 관리 객체의 포인터 @return 마지막 문자열 포인터 *///---------------------------------------------------------------------------- char *tstrlist_last ( tstrlist *that ) { tlist *tlst = that->ftlst; return tstrlist_get_string( that, tlst->fcount-1 ); } //------------------------------------------------------------------------------ /** @brief 특정 아이템의 위치(인덱스)를 변경한다. @param that 관리 객체의 포인터 @param curindex 변경할 아이템의 인덱스 @param newindex 변경될 아이템의 인덱스 *///---------------------------------------------------------------------------- void tstrlist_move ( tstrlist *that, int curindex, int newindex ) { tlist *tlst = that->ftlst; tlist_move( tlst, curindex, newindex ); } //------------------------------------------------------------------------------ /** @brief 특정아이템의 문자열을 변경한다. @param that 관리 객체의 포인터 @param index 문자열이 변경될 인덱스 @param str 새로 변경될 문자열 *///---------------------------------------------------------------------------- void tstrlist_put_string ( tstrlist *that, int index, char *str ) { tlist *tlst = that->ftlst; tstritem *sitem; sitem = tlist_get( tlst, index ); if ( sitem ) { sitem = tstrlist_replace_itemstr( sitem, str ); tlist_put( tlst, index, sitem ); } } //------------------------------------------------------------------------------ /** @brief 특정아이템의 사용자 메모리 변수를 변경한다. @param that 관리 객체의 포인터 @param index 변경될 아이템 인덱스 @param obj 새로 변경될 사용자 포인터 *///---------------------------------------------------------------------------- void tstrlist_put_object ( tstrlist *that, int index, void *obj ) { tlist *tlst = that->ftlst; tstritem *sitem; sitem = tlist_get( tlst, index ); if ( sitem ) { sitem->fdata = obj; } } //------------------------------------------------------------------------------ /** @brief 특정아이템의 태그변수를 변경한다. @param that 관리 객체의 포인터 @param index 태그가 변경될 인덱스 @param tag 새로 변경될 정수형 태그변수 *///---------------------------------------------------------------------------- void tstrlist_put_tag ( tstrlist *that, int index, int tag ) { tlist *tlst = that->ftlst; tstritem *sitem; sitem = tlist_get( tlst, index ); if ( sitem ) { sitem->ftag = tag; } } //------------------------------------------------------------------------------ /** @brief 인자로 전해준 동일한 문자열을 찾아 삭제한다. @param that 관리 객체의 포인터 @param item 삭제할 아이템의 포인터 @return 삭제된 아이템의 과거 인덱스 *///---------------------------------------------------------------------------- int tstrlist_remove ( tstrlist *that, char *str ) { int result; result = tstrlist_indexof( that, str ); if( result >= 0 ) tstrlist_delete( that, result ); return result; } //------------------------------------------------------------------------------ /** @brief 메모리 관리를 위해 사용하지 않는 메모리를 반환한다. @param that 관리 객체의 포인터 @remark 실제 메모리를 반환하지 않는다. @todo 메모리를 반환하도록 재작성되어야 한다. *///---------------------------------------------------------------------------- void tstrlist_pack ( tstrlist *that ) { tlist *tlst = that->ftlst; tlist_pack( tlst ); } //------------------------------------------------------------------------------ /** @brief 아이템의 개수를 얻는다. @param that 관리 객체의 포인터 @return 아이템의 개수 *///---------------------------------------------------------------------------- int tstrlist_getcount ( tstrlist *that ) { tlist *tlst = that->ftlst; return tlst->fcount; } //------------------------------------------------------------------------------ /** @brief 문자열 정렬을 위해 크기를 비교한다. @param astr 비교 포인터 @param bstr 비교 포인터 @return 문자열 비교값 *///---------------------------------------------------------------------------- static int tstrlist_sortfunc( const void *ppa, const void *ppb ) { tstritem **aitem, **bitem; aitem = (tstritem **)ppa; bitem = (tstritem **)ppb; return strcmp( (*aitem)->fstr, (*bitem)->fstr ); } //------------------------------------------------------------------------------ /** @brief 아이템을 사용자 비교함수를 통해 정렬한다. @param that 관리 객체의 포인터 @param tstrlistsortcomparefunc 사용자비교 콜백함수이며, int (*func)(const void *, const void *) 형태이다. *///---------------------------------------------------------------------------- void tstrlist_sort ( tstrlist *that ) { tlist *tlst = that->ftlst; if ( 0 >= tlst->fcount ) return; tlist_sort( tlst, tstrlist_sortfunc ); } //------------------------------------------------------------------------------ /** @brief 인자로 전해준 문자열을 분리하여 아이템으로 추가한다. @param that 관리 객체의 포인터 @param str 분리할 문자열 @return 객체가 관리하는 아이템 개수 @todo 더블쿼테이션(") 으로 싸여진 문자열 분리가 필요하다. *///---------------------------------------------------------------------------- int tstrlist_commatext ( tstrlist *that, char *str ) { #define COMMA_BUFF_MAX 4096 tlist *tlst = that->ftlst; int ndx_sour; int ndx_buff; char ch_division = '\0'; char buff[COMMA_BUFF_MAX+1]; void add_buff_to_list( void) { trim( buff); tstrlist_add( that, buff); } ndx_buff = 0; // 버퍼에 문자를 넣을 위치를 0으로 초기화 for ( ndx_sour = 0; ndx_sour < strlen( str); ndx_sour++) { if ( '\0' == ch_division) { switch( str[ndx_sour]) { case '\'' : case '\"' : if ( 0 < ndx_buff) // 이전에 버퍼로 등록된 문자열이 있다면 리스트에 추가 { buff[ndx_buff] = '\0'; add_buff_to_list(); } ch_division = str[ndx_sour]; ndx_buff = 0; // 버퍼에 새로운 문자열을 담을 수 있도록 버퍼의 위치를 0 으로 초기화 break; case ' ' : case ',' : case '\n' : case '\r' : if ( 0 < ndx_buff) // 이전에 버퍼로 등록된 문자열이 있다면 리스트에 추가 { buff[ndx_buff] = '\0'; add_buff_to_list(); ndx_buff = 0; } break; default : if ( ndx_buff < COMMA_BUFF_MAX) { buff[ndx_buff++] = str[ndx_sour]; } else { printf( "tstrlist error: buffer is small in comma text function."); } break; } } else { if ( ch_division == str[ndx_sour]) // 이전 인용부호의 끝이라면 { ch_division = '\0'; buff[ndx_buff] = '\0'; add_buff_to_list(); ndx_buff = 0; } else { if ( ndx_buff < COMMA_BUFF_MAX) { buff[ndx_buff++] = str[ndx_sour]; } else { printf( "tstrlist error: buffer is small in comma text function."); } } } } if ( 0 < ndx_buff) // 이전에 버퍼로 등록된 문자열이 있다면 리스트에 추가 { buff[ndx_buff] = '\0'; add_buff_to_list(); } return tlst->fcount; } //------------------------------------------------------------------------------ /** @brief 텍스트파일에서 라인별로 아이템에 등록한다. @param that 관리 객체의 포인터 @param fname 파일이름 @return 객체가 관리하는 아이템 개수 *///---------------------------------------------------------------------------- int tstrlist_load_from_file ( tstrlist *that, char *fname ) { tlist *tlst = that->ftlst; char line[2048]; FILE *pfile; pfile = fopen( fname, "r" ); if ( pfile ) { while( fgets( line, sizeof(line), pfile ) ) { __trimstr( line ); if ( 0 < strlen(line) ) { tstrlist_add( that, line ); } } fclose( pfile ); } return tlst->fcount; } //------------------------------------------------------------------------------ /** @brief 아이템들을 라인별로 파일로 저장한다. @param that 관리 객체의 포인터 @param fname 파일이름 @return 파일에 저장한 라인수 *///---------------------------------------------------------------------------- int tstrlist_save_to_file ( tstrlist *that, char *fname ) { tlist *tlst = that->ftlst; FILE *pfile; int loop, wrline; pfile = fopen( fname, "w+" ); wrline = 0; if ( pfile ) { for (loop=0; loopfcount; loop++) { if ( 0 < fprintf( pfile, "%s\n", tstrlist_get_string( that, loop ) ) ) wrline ++; } fclose( pfile ); } return wrline; }