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 파일을 만들어 보기로 하죠. XMLCPP Library 0.91 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"", L"title...

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 switch (pp.get_event_type()) { case PullParser::START_TAG: wcout for (int i = 0; i...