Skip to main content

Posts

Showing posts from November, 2006

C++ of the Day #36 - Polymorphic Predicate

오랫만에 올리는 C++ of the Day입니다. :-) Question 파일 리스트를 필터링하는 기능을 구현하려고 합니다. 필터링에는 다수의 필터가 사용되며 따라서 다음과 같이 구현하려고 합니다. ((이번 글은 STL algorithm member function problem 을 가지고 작성되었습니다.)) struct Rule : std::unary_function { virtual result_type operator()(const argument_type&) const = 0; }; // concrete rules are inherited from the Rule class and define the operator() typedef boost::shared_ptr RulePtr; vector filelist; // ... fill filelist with a series of file names ... for(vector ::iterator iter = rules.begin(); iter != rules.end(); ++iter) { // This is the problem line... remove_if(fileList.begin(), fileList.end(), ??); } 이 기능을 제대로 구현하려면 어떻게 수정해야 할까요? Answer 위의 코드는 크게 두가지 문제가 있습니다. 첫째는 remove_if 함수의 선언을 보면 알 수 있습니다. template ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, Predicate pred); 여기서 Predicate의 model은 결국 Assignable 임을 알 수 있습니다. 따라서 ?? 부분을 **iter와 같이 할 경우 remove_if의 Predicate template parameter는 Rule로 instantiation되며 Rule 클래스는 pure virtual로 Assignable하지

#ifdef...#endif와 Boost::Any

코딩을 하다 보면 #ifdef...#endif등의 preprocesor를 사용하게 되는 경우들이 있습니다. 주로 portable한 코드를 작성하기 위해 사용하곤 하지요. 이번 XMLCPP 라이브러리 구현중에 이와 유사한 필요가 생겼습니다. Unicode encoding, decoding을 위해 libiconv 라이브러리 를 사용하던 것을 libiconv없이도 사용할 수 있는 옵션을 만들기 위해서입니다. libiconv 라이브러리가 많은 encoding을 지원하여 좋긴 하지만 GNU license라 사용에 제약이 많은 편입니다. 제가 만드는 XMLCPP는 이런 제약 없이 모든 곳에서 사용할 수 있게 하고 싶어 자체적으로 encoding, decoding을 하는 코드를 집어 넣었습니다. ((물론 지원하는 encoding이 libiconv보다 적습니다. 현재 자체 코드에서 지원하는 encoding은 다음과 같습니다. char, wchar_t UTF-8 UCS-2, UCS-2BE, UCS-2LE UTF-16, UTF-16BE, UTF-16LE UCS-4, UCS-4BE, UCS4-LE UTF-32, UTF-32BE, UTF-32LE )) 기본으로 libiconv를 사용하지 않도록 Makefile이 만들어져 있으며 libiconv를 사용하고 싶다면 Makefile에서 USE_ICONV 변수를 YES로 셋팅해 주면 됩니다. 먼저 자체 encoding, decoding 버전을 구현하기 전의 CodeConvImpl 클래스는 대략 다음과 같았습니다. ((여기서 CodeConvImpl 클래스는 CodeConv 클래스의 Pimpl Idiom 을 위한 구현입니다.)) #include class CodeConvImpl { public: // ... private: iconv_t desc_; // iconv.h에서 정의된 타입 }; 이제 이를 컴파일러 옵션에 따라 iconv를 사용하지 않거나 혹은 사용하게 하려면 다음과 같이 할 수 있습니다. #ifdef

XMLCPP Library 0.91

오랫만에 포스팅이네요. 요새 XMLCPP 만드는 재미에 빠져서요. :-) XMLCPP 0.91 버전을 release 했습니다. 0.9버전의 코드와 디렉토리들을 좀 정리한 내용도 있지만 가장 큰 변화는 Serializer 클래스가 구현되었다는 점입니다. PullParser가 XML을 읽기 위한 인터페이스라면 Serializer는 XML을 쓰기 위한 인터페이스입니다. 간단한 예로 다음 XML 파일을 만들어 보기로 하죠. <br/> XMLCPP Library 0.91<br/> blah blah 먼저 Serializer instance를 생성하고 원하는 feature를 activate한 후 output target을 지정합니다. 여기서는 "filename.xml"이라는 파일에 쓰기로 하겠습니다. ofstream fs("filename.xml"); Serializer sr; sr.set_feature(Serializer::LINE_SEPARATOR); sr.set_feature(Serializer::INDENTATION); sr.set_output("UTF-8", fs); 만약 LINE_SEPARATOR feature를 사용하지 않는다면 XML 전체 출력이 한줄로 됩니다. 물론 ignorable_whitespace() 함수를 사용하여 직접 줄바꿈이나 들여쓰기를 할 수도 있습니다. Serializer instance가 준비되었으므로 이제 쓰면 됩니다. ;-) start_tag(), end_tag() 함수의 첫번째 인자는 namespace를 나타내는데 이 예제에서는 사용하지 않으므로 모두 null string을 사용하였습니다. sr.start_document(L"UTF-8", L""); sr.start_tag(L"", L"post"); sr.start_tag(L"&q

XMLCPP Library 0.9

며칠간 뚝딱거려서 만든 XMLCPP Library의 최초 버전을 release하였습니다. 라이브러리의 홈페이지 에서 간단한 사용법을 보실 수 있습니다. 라이브러리가 지원하는 표준은 다음과 같습니다. XmlPull v1 API XML InfoSet 의 모든 문법 XML Namespaces XML Recommendation에 정의된 CharClasses 현재 DTD를 사용한 validation은 구현되어 있지 않습니다. 간단히 말하면 non-validating XML pull parser입니다. 물론 DTD에 대한 문법 검사는 수행합니다. ((이 기능은 Roadmap에 따라 차후 구현될 예정입니다.)) Entity ref를 위한 name/value pair는 XmlPull v1 API에 정의되어 있는 define_entity_replacement_text(name, text)를 사용하여 수동으로 입력하여 사용할 수 있습니다. Requirements 이 XMLCPP Library를 사용하기 위해서는 다음의 두 라이브러리가 필요합니다. ((둘 다 Windows 환경에서도 사용 가능합니다만 아직 Windows로의 포팅 작업은 이루어지지 않았습니다. Roadmap 부분을 참고하세요.)) Boost C++ Library libiconv Usage 구현된 PullParser의 간단한 사용예는 다음과 같습니다. using namespace xmlcpp; try { fstream fs(filename); fs.exceptions (ios_base::badbit); PullParser pp; pp.set_input(fs, encoding); while (pp.next() != PullParser::END_DOCUMENT) { wcout << PullParser::event_type_c_str(pp.get_event_type()) << L": " << end