[med-svn] [libgtextutils] 33/83: Added Tuple-Parser template class.
Charles Plessy
plessy at moszumanska.debian.org
Wed Jan 8 13:37:27 UTC 2014
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 <gordon at cshl.edu>
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
More information about the debian-med-commit
mailing list