[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