This is an automated email from the git hooks/post-receive script. plessy pushed a commit to branch debian/unstable in repository libgtextutils.
commit 985328d87c2dc69178a99664208e282646f51c34 Author: A. Gordon <[email protected]> Date: Sun Apr 5 23:19:11 2009 -0400 Added Tuple-Parser template class. --- src/gtextutils/Makefile.am | 10 +- src/gtextutils/tuple_parser.h | 446 ++++++++++++++++++++++++++++++++++++++++++ tests/Makefile.am | 9 +- 3 files changed, 461 insertions(+), 4 deletions(-) diff --git a/src/gtextutils/Makefile.am b/src/gtextutils/Makefile.am index 034ead1..049d88d 100644 --- a/src/gtextutils/Makefile.am +++ b/src/gtextutils/Makefile.am @@ -16,7 +16,10 @@ libgtextutils_0_2_a_SOURCES = stream_wrapper.cpp stream_wrapper.h \ container_join.h \ natsort.h \ strnatcmp.c strnatcmp.h \ - outbuf3.hpp + outbuf3.hpp \ + tuple_parser.h \ + inbuf1.hpp \ + pipe_fitter.c pipe_fitter.h libgtextutils_0_2_a_includedir = $(includedir)/gtextutils-0.2/gtextutils @@ -25,4 +28,7 @@ libgtextutils_0_2_a_include_HEADERS = container_join.h \ stream_wrapper.h \ natsort.h \ strnatcmp.h \ - outbuf3.hpp + outbuf3.hpp \ + inbuf1.hpp \ + tuple_parser.h \ + pipe_fitter.h diff --git a/src/gtextutils/tuple_parser.h b/src/gtextutils/tuple_parser.h new file mode 100644 index 0000000..e0e68bf --- /dev/null +++ b/src/gtextutils/tuple_parser.h @@ -0,0 +1,446 @@ +#ifndef __TUPLE_PARSER_H__ +#define __TUPLE_PARSER_H__ + +#include <typeinfo> +#include <bitset> +#include <sstream> +#include <stdexcept> +#include <tr1/tuple> + +//This #pramga allows variadic templates +//in a header file (imitating tr1/tuple) +#pragma GCC system_header + +//#define TUPLE_PARSER_DEBUG + +/* + The maximun valid number for a column. + The value is used in a bitset to prevent duplicated columns. +*/ +#ifndef TUPLE_PARSER_MAX_COLUMN_NUMBER +#define TUPLE_PARSER_MAX_COLUMN_NUMBER (128) +#endif + +/* + Premature-end-of-line exception. + + Specialized exception class, which can report back the + number of actual columns and expected columns. + + The what() still produces a user-friendly string, + so if the exception is not caught, the report will still + make some sense. +*/ +class tuple_parser_premature_end_of_line : public std::runtime_error +{ +private: + std::string _what; + +public: + tuple_parser_premature_end_of_line(size_t expected_columns, size_t actual_columns) : + std::runtime_error("") + { + std::ostringstream os; + os << "Error: premature end-of-line, expecting at least " + << expected_columns + << " columns, got only " + << actual_columns + << " columns" ; + + _what = os.str(); + } + + virtual const char* what() const throw() + { + return _what.c_str(); + } + + virtual ~tuple_parser_premature_end_of_line() throw() + { + } +}; + +/* + Parse Error exception. + + Specialized exception class, which can report back the + number of the failed column. + + The what() still produces a user-friendly string, + so if the exception is not caught, the report will still + make some sense. +*/ +class tuple_parser_parsing_error: public std::runtime_error +{ +private: + std::string _what; + +public: + tuple_parser_parsing_error(size_t column) : + std::runtime_error("") + { + std::ostringstream os; + os << "Error: invalid input in column " + << column ; + + _what = os.str(); + } + + virtual const char* what() const throw() + { + return _what.c_str(); + } + + virtual ~tuple_parser_parsing_error() throw() + { + } +}; + +/* + Tiny hack to convert every type into a size_t. + + Used in the constructor of _Tuple_Parser_impl, + so that for all lists of template types, + the constructor will accept list of size_t as arguments. + + Usage Example: + + template<typename _Elements...> + class MyClass + { + public: + //This 'regular' constructor accepts variables with the same + //Type of the template arguments. + + MyClass ( _Elements... vars ) ; + + + + //This constructor accepts variables of type size_t, + //regardless of the actual type of the + //template arguments. + + MyClass ( typename __column_index<_Elements>::type... vars ) ; + }; + + + The outcome: + A class with the following four template arguments: + + MyClass<double,string,int,char> + + will have a constructor accepting four 'size_t' arguments: + + MyClass::MyClass(size_t, size_t, size_t, size_t) + + + Modeled after tr1/tuple's __add_c_ref helper structs. +*/ +template<typename _Tp> +struct __column_index +{ + typedef size_t type; +}; + + + + +/* + Tuple-Parser starts here. + + + +*/ + +template<int _Idx, typename... _Elements> + class _Tuple_Parser_impl; + +/* + Zero-element tuple implementation. + This is the basis case for the inheritance recursion. + + used_column_bitset is used (during runtime) do make + sure there are no duplicates in column numbers. + + max_column_number is used (during runtime) do deduce the + maximum required column number. + + Since column assignment is done in runtime (not during compile-time), + this can not be inlined or meta-programmed. + + Inherited sub-classes should call 'update_used_column()' + in their constructor to add a new column number. +*/ +template<int _Idx> +class _Tuple_Parser_impl<_Idx> +{ +private: + size_t max_column_number ; + std::bitset<TUPLE_PARSER_MAX_COLUMN_NUMBER> used_column_bitset; + +public: + _Tuple_Parser_impl() : + max_column_number(0) + { +#ifdef TUPLE_PARSER_DEBUG + std::cerr << "At base, _Idx = " << _Idx << std::endl; +#endif + } + + void update_max_column_number(size_t num) + { + max_column_number = std::max(max_column_number,num); + } + + void update_used_column ( size_t column ) + { + if ( column >= TUPLE_PARSER_MAX_COLUMN_NUMBER ) { + std::ostringstream os; + os << "Internal error: Invalid column number (" << column + << "). maximum allowed value is " << TUPLE_PARSER_MAX_COLUMN_NUMBER + << ". To change this value, re-define TUPLE_PARSER_MAX_COLUMN_NUMBER in " \ + __FILE__ " and re-compile the program. "; + throw std::length_error ( os.str() ) ; + } + + if ( used_column_bitset.test ( column ) ) { + std::ostringstream os; + os << "Error: column number " << column + << " is used more than once." ; + throw std::invalid_argument( os.str() ) ; + } + + used_column_bitset.set(column); + update_max_column_number(column) ; + } + + size_t max_column() const { return max_column_number ; } +#ifdef TUPLE_PARSER_DEBUG + void print() const {} +#endif + bool consume_input ( size_t , std::istream& ) { return false; } +}; + +/* + The heart of the Tuple Parser recursive implementation. + + Modeled after GCC-4.3.2's <tr1/tuple>. + + At compile time, the types of the fields is recursively set + (just like in a tuple). + + At run time, the constructor accepts the column number for each + field, and the 'read_from_stream()' method extract the fields + from the given input stream (according to the column numbers). + + Users should use a Tuple_Parser<> instead of _Tuple_Parser_impl<>. + + + Usage exmaple: + + //Define a parser that extracts three fields from an input stream: + //an int, a string and a double. + + typedef Tuple_Parser<int,std::string,double> MyParser ; + + + //Create a parser object, that will expect + //the int field to be on the 8th column, + //the string field to be the 4th column, + //and the double field to be on the 2nd column. + //the other columns will be skipped and ignored. + + MyParser p(8,4,2); + + //Extract the columns from the input stream. + istringstream is ( "DUMMY1 3.14 DUMMY3 HELLO DUMMY5 DUMMY6 DUMMY7 42 DUMMY9" ) ; + is >> p ; + + //Get the extracted values. + int a = get<0>(p); + string s = get<1>(p); + double d = get<2>(p); +*/ +template<int _Idx, typename _Head, typename... _Tail> +struct _Tuple_Parser_impl<_Idx, _Head, _Tail...> +: public _Tuple_Parser_impl<_Idx + 1, _Tail...> +{ + typedef _Tuple_Parser_impl<_Idx + 1, _Tail...> _Inherited; + + typedef _Head _M_head_type; + _M_head_type _M_head ; + size_t _M_head_column ; + + _Inherited& _M_tail() { return *this; } + const _Inherited& _M_tail() const { return *this; } + + _Tuple_Parser_impl() : _Inherited(), _M_head_column(_Idx+1),_M_head() { } + + _Tuple_Parser_impl( size_t _head_column, typename __column_index<_Tail>::type... __tail) : + _Inherited(__tail...), _M_head_column(_head_column) + { + update_used_column ( _M_head_column ) ; +#ifdef TUPLE_PARSER_DEBUG + std::cerr << "At Ctor, _Idx = " << _Idx + << " Max-Column-Number = " << _M_tail().max_column() + << std::endl; +#endif + } + +#ifdef TUPLE_PARSER_DEBUG + void print() const + { + std::cout << "_Idx=" << _Idx << " " + << "typeid(head)=" << typeid(_M_head).name() + << " column = " << _M_head_column + << " value = " << _M_head + << std::endl ; + + _M_tail().print() ; + } +#endif + + void read_from_stream(std::istream& strm) + { + size_t current_column = 0 ; + while ( strm && !strm.eof() ) { + current_column++; + if ( ! consume_input ( current_column, strm ) ) { + //consume input with dummy variable + std::string dummy ; + strm >> dummy ; +#ifdef TUPLE_PARSER_DEBUG + std::cout << "skipping column " + << current_column + << std::endl; +#endif + } + } + if (current_column<_M_tail().max_column()) { + throw tuple_parser_premature_end_of_line ( _M_tail().max_column(), + current_column ) ; + } + } + + bool consume_input ( size_t column_number, std::istream& strm ) + { + if ( column_number == _M_head_column ) { +#ifdef TUPLE_PARSER_DEBUG + std::cout << "consuming column " + << column_number + << ", _Idx = " + << _Idx << std::endl; +#endif + strm >> _M_head; + + if (!strm) + throw tuple_parser_parsing_error(column_number); + + return true; + } + return _M_tail().consume_input ( column_number, strm ) ; + } + + void update_used_column (size_t num) { _M_tail().update_used_column(num); } + size_t max_column() const { return _M_tail().max_column() ; } + +}; + + + +/* + Tuple_Parser - + The user-friendly version of _Tuple_Parser_impl. + + See comments of _Tuple_Parser_impl for details. +*/ +template <typename... _Elements> +struct Tuple_Parser : public _Tuple_Parser_impl<0,_Elements...> +{ + Tuple_Parser ( typename __column_index<_Elements>::type... _UElements) : + _Tuple_Parser_impl<0, _Elements...>(_UElements...) + { } +}; + + +/* + Template to get the type of the Nth element + in a tuple parser. + copied from 'tr1/tuple', based on tuple_element<> template. + + Usage Example: + + typedef Tuple_Parser<int, double, std::string, float> MyParser ; + + // 'MyVariable' will have type std::string, + // which is the third (index=2) element in MyParser ) + tuple_parser_element<2, MyParser>::type MyVariable ; + +*/ +/// Gives the type of the ith element of a given tuple type. +template<int __i, typename _Tp> +struct tuple_parser_element; + +/** +* Recursive case for tuple_element: strip off the first element in +* the tuple and retrieve the (i-1)th element of the remaining tuple. +*/ +template<int __i, typename _Head, typename... _Tail> +struct tuple_parser_element<__i, Tuple_Parser<_Head, _Tail...> > +: tuple_parser_element<__i - 1, Tuple_Parser<_Tail...> > { }; + +/** +* Basis case for tuple_element: The first element is the one we're seeking. +*/ +template<typename _Head, typename... _Tail> +struct tuple_parser_element<0, Tuple_Parser<_Head, _Tail...> > +{ +typedef _Head type; +}; + + + + + + +/* + Get the value of the Nth element in a Tuple_Parser. + + Copied almost verbatim from <tr1/tuple>. + + See comments of _Tuple_Parser_impl for usage example. +*/ +// Adds a const reference to a non-reference type. +template<int __i, typename _Head, typename... _Tail> +inline typename std::tr1::__add_c_ref<_Head>::type +__get_helper(const _Tuple_Parser_impl<__i, _Head, _Tail...>& __t) +{ +return __t._M_head; +} + +template<int __i, typename... _Elements> +inline typename std::tr1::__add_c_ref< + typename tuple_parser_element<__i, Tuple_Parser<_Elements...> >::type + >::type +get(const Tuple_Parser<_Elements...>& __t) +{ +return __get_helper<__i>(__t); +} + + +/* + Input Stream operator for Tuple_Parser + + + See comments of _Tuple_Parser_impl for usage example. +*/ +template<typename... _Elements> +std::istream& operator>> ( std::istream& strm, _Tuple_Parser_impl<0, _Elements... > &parser ) +{ + parser.read_from_stream(strm); + return strm; +} + + +#endif + diff --git a/tests/Makefile.am b/tests/Makefile.am index dd19959..772e623 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -17,7 +17,10 @@ check_PROGRAMS = test_container_join \ test_input_stream_wrapper \ test_text_reader \ test_text_reader_unget \ - test_fd_outbuf + test_fd_outbuf \ + test_fd_inbuf \ + test_in_out_buf \ + test_pipe_fitter TESTS = $(check_PROGRAMS) @@ -30,4 +33,6 @@ test_input_stream_wrapper_SOURCES = test_input_stream_wrapper.cpp test_text_reader_SOURCES = test_text_reader.cpp test_text_reader_unget_SOURCES = test_text_reader_unget.cpp test_fd_outbuf_SOURCES = test_fd_outbuf.cpp - +test_fd_inbuf_SOURCES = test_fd_inbuf.cpp +test_in_out_buf_SOURCES = test_in_out_buf.cpp +test_pipe_fitter_SOURCES = test_pipe_fitter.c -- Alioth's /git/debian-med/git-commit-notice on /srv/git.debian.org/git/debian-med/libgtextutils.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
