#include <string>
#include <fstream>
-DEAL_II_NAMESPACE_OPEN
// we only need output streams, but older compilers did not provide
// them in a separate include file
#ifdef HAVE_STD_OSTREAM_HEADER
# include <iostream>
#endif
+#include <boost/variant.hpp>
-/**
- * Abstract base class for the <tt>TableEntry</tt> class. See there.
- * This class is not to be used by the user.
- *
- * @ingroup textoutput
- * @author Ralf Hartmann, 1999
- */
-class TableEntryBase
-{
- public:
- /**
- * Constructor.
- */
- TableEntryBase();
-
- /**
- * Virtual destructor.
- */
- virtual ~TableEntryBase();
-
- /**
- * Write the table entry as text.
- */
- virtual void write_text (std::ostream &) const = 0;
-
- /**
- * Write the table entry in tex format.
- */
- virtual void write_tex (std::ostream &) const = 0;
-};
+DEAL_II_NAMESPACE_OPEN
-/**
- * A <tt>TableEntry</tt> stores the value of a table entry.
- * The value type of this table entry is arbitrary. For
- * a <tt>TableEntry<typename value_type></tt> with a non-common value
- * type you may want to specialize the output functions in order
- * to get nicer output. This class is not to be used by the user.
- *
- * For more detail see the <tt>TableHandler</tt> class.
- *
- * @ingroup textoutput
- * @author Ralf Hartmann, 1999
- */
-template <typename value_type>
-class TableEntry : public TableEntryBase
+namespace internal
{
- public:
- /**
- * Constructor.
- */
- TableEntry (const value_type value);
-
- /**
- * Destructor.
- */
- virtual ~TableEntry();
-
- /**
- * Returns the value of this
- * table entry.
- */
- value_type value () const;
-
- /**
- * Write the table entry as text.
- */
- virtual void write_text (std::ostream &out) const;
-
- /**
- * Write the table entry in tex
- * format.
- */
- virtual void write_tex (std::ostream &out) const;
-
- private:
- /**
- * Stored value.
- */
- const value_type val;
-};
+ /**
+ * A <tt>TableEntry</tt> stores the value of a table entry.
+ * It can either be of type int, unsigned int, double or std::string.
+ * In essence, this structure is the same as
+ * <code>boost::variant<int,unsigned int,double,std::string></code>
+ * but we wrap this object in a structure for which we can write
+ * a function that can serialize it. This is also why the function
+ * is not in fact of type boost::any.
+ */
+ struct TableEntry
+ {
+ /**
+ * Abbreviation for the data type stored by this object.
+ */
+ typedef boost::variant<int,unsigned int,double,std::string> value_type;
+
+ /**
+ * Return the value stored by this object. The template type
+ * T must be one of <code>int,unsigned int,double,std::string</code>
+ * and it must match the data type of the object originally stored
+ * in this TableEntry object.
+ */
+ template <typename T>
+ T get () const;
+
+ /**
+ * Return the numeric value of this object if data has been stored in
+ * it either as an integer, an unsigned integer, or a double.
+ *
+ * @return double
+ **/
+ double get_numeric_value () const;
+
+ /**
+ * Stored value.
+ */
+ value_type value;
+ };
+}
/**
* @endcode
*
* @ingroup textoutput
- * @author Ralf Hartmann, 1999
+ * @author Ralf Hartmann, 1999; Wolfgang Bangerth, 2011
*/
class TableHandler
{
/**
* Constructor needed by STL maps.
*/
- Column();
+ Column ();
/**
* Constructor.
*/
- Column(const std::string &tex_caption);
+ Column (const std::string &tex_caption);
- /**
- * Destructor.
- */
- ~Column();
/**
* List of entries within
- * this column. They may
- * actually be of very
- * different type, since we
- * use the templated
- * <tt>TableEntry<T></tt> class
- * for actual values, which
- * is only a wrapper for
- * <tt>T</tt>, but is derived from
- * <tt>TableEntryBase</tt>.
+ * this column. Values are
+ * always immediately
+ * converted to strings to
+ * provide a uniform method
+ * of lookup.
*/
- std::vector<TableEntryBase *> entries;
+ std::vector<internal::TableEntry> entries;
/**
* The caption of the column
* The label of the table.
*/
std::string tex_table_label;
-
};
+
+// inline and template functions
+namespace internal
+{
+ template <typename T>
+ inline
+ T TableEntry::get () const
+ {
+ // we don't quite know the data type in 'value', but
+ // it must be one of the ones in the type list of the
+ // boost::variant. so if T is not in the list, or if
+ // the data stored in the TableEntry is not of type
+ // T, then we will get an exception that we can
+ // catch and produce an error message
+ try
+ {
+ return boost::get<T>(value);
+ }
+ catch (...)
+ {
+ Assert(false, ExcMessage ("This TableEntry object does not store a datum of type T"));
+ throw;
+ }
+ }
+
+
+ inline
+ double TableEntry::get_numeric_value () const
+ {
+ // we don't quite know the data type in 'value', but
+ // it must be one of the ones in the type list of the
+ // boost::variant. Go through this list and return
+ // the value if this happens to be a number
+ //
+ // first try with int
+ try
+ {
+ return boost::get<int>(value);
+ }
+ catch (...)
+ {}
+
+
+ // ... then with unsigned int...
+ try
+ {
+ return boost::get<unsigned int>(value);
+ }
+ catch (...)
+ {}
+
+ // ...and finally with double precision:
+ try
+ {
+ return boost::get<double>(value);
+ }
+ catch (...)
+ {
+ Assert (false, ExcMessage ("The number stored by this element of the "
+ "table is not a number."))
+ }
+
+ return 0;
+ }
+}
+
DEAL_II_NAMESPACE_CLOSE
#endif
// $Id$
// Version: $Name$
//
-// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 by the deal.II authors
+// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2011 by the deal.II authors
//
// This file is subject to QPL and may not be distributed
// without copyright and license information. Please refer
#include <sstream>
#include <iostream>
#include <iomanip>
+#include "../../contrib/boost-1.46.1/include/boost/mpl/string.hpp"
DEAL_II_NAMESPACE_OPEN
-
-TableEntryBase::TableEntryBase ()
-{}
-
-
-TableEntryBase::~TableEntryBase ()
-{}
-
/*---------------------------------------------------------------------*/
-template <typename number>
-TableEntry<number>::TableEntry(const number value)
- :
- val(value)
-{}
-
-
-
-template <typename number>
-TableEntry<number>::~TableEntry()
-{}
-
-
-
-template <typename number>
-number TableEntry<number>::value() const
-{
- return val;
-}
-
-
-
-template <typename number>
-void TableEntry<number>::write_tex (std::ostream &out) const
-{
- out << val;
-}
-
-
-
-template <typename number>
-void TableEntry<number>::write_text (std::ostream &out) const
-{
- out << val;
-}
-
-
-/*---------------------------------------------------------------------*/
TableHandler::Column::Column(const std::string &tex_caption)
:
tex_format("c"),
precision(4),
scientific(0),
- flag(0)
+ flag(0)
{}
tex_format("c"),
precision(4),
scientific(0),
- flag(0)
+ flag(0)
{}
-TableHandler::Column::~Column()
-{
- for (unsigned int i=0; i<entries.size(); ++i)
- delete entries[i];
- entries.clear();
-}
-
/*---------------------------------------------------------------------*/
{}
+
template <typename number>
-void TableHandler::add_value (const std::string &key,
+void TableHandler::add_value (const std::string &key,
const number value)
{
- if (!columns.count(key))
+ if (columns.find(key) == columns.end())
{
std::pair<std::string, Column> new_column(key, Column(key));
columns.insert(new_column);
column_order.push_back(key);
}
-
- TableEntry<number> *entry_ptr=new TableEntry<number>(value);
- const std::map<std::string, Column>::iterator col_iter=columns.find(key);
- Assert(col_iter!=columns.end(), ExcInternalError());
-
- col_iter->second.entries.push_back(entry_ptr);
+
+ const internal::TableEntry entry = { value };
+ columns[key].entries.push_back (entry);
}
+
void TableHandler::add_column_to_supercolumn (const std::string &key,
const std::string &superkey)
{
column_order[j]=superkey;
break;
}
- }
- else
+ }
+ else
{
// remove key from column_order
// for erase we need an iterator
- for (std::vector<std::string>::iterator order_iter=column_order.begin();
+ for (std::vector<std::string>::iterator order_iter=column_order.begin();
order_iter!=column_order.end(); ++order_iter)
if (*order_iter==key)
{
}
+
void TableHandler::set_column_order (const std::vector<std::string> &new_order)
{
for (unsigned int j=0; j<new_order.size(); ++j)
}
-void TableHandler::set_tex_caption (const std::string &key,
+void TableHandler::set_tex_caption (const std::string &key,
const std::string &tex_caption)
{
Assert(columns.count(key), ExcColumnNotExistent(key));
columns[key].tex_caption=tex_caption;
}
+
+
void TableHandler::set_tex_table_caption (const std::string &table_caption)
{
tex_table_caption=table_caption;
}
+
+
void TableHandler::set_tex_table_label (const std::string &table_label)
{
tex_table_label=table_label;
}
+
+
void TableHandler::set_tex_supercaption (const std::string &superkey,
const std::string &tex_supercaption)
{
}
+
void TableHandler::set_tex_format (const std::string &key,
const std::string &tex_format)
{
}
+
void TableHandler::set_precision (const std::string &key,
const unsigned int precision)
{
void TableHandler::write_text(std::ostream &out) const
{
- AssertThrow (out, ExcIO());
-
+ AssertThrow (out, ExcIO());
+
std::vector<std::string> sel_columns;
get_selected_columns(sel_columns);
const std::map<std::string, Column>::const_iterator
col_iter=columns.find(key);
Assert(col_iter!=columns.end(), ExcInternalError());
-
+
const Column & column = col_iter->second;
// write it into a dummy
// stream, just to get its
// size upon output
std::ostringstream dummy_out;
-
+
dummy_out << std::setprecision(column.precision);
if (col_iter->second.scientific)
dummy_out.setf (std::ios::scientific, std::ios::floatfield);
else
dummy_out.setf (std::ios::fixed, std::ios::floatfield);
- column.entries[i]->write_text (dummy_out);
-
+
+ dummy_out << column.entries[i].value;
+
// get size, note that we are
// not interested in the
// trailing \0
for (unsigned int j=0; j<column_order.size(); ++j)
{
const std::string & key = column_order[j];
-
+
// if the key of this column is
// wider than the widest entry,
// then adjust
out << ' ';
}
out << std::endl;
-
+
for (unsigned int i=0; i<nrows; ++i)
- {
+ {
for (unsigned int j=0; j<n_cols; ++j)
{
std::string key=sel_columns[j];
const std::map<std::string, Column>::const_iterator
col_iter=columns.find(key);
Assert(col_iter!=columns.end(), ExcInternalError());
-
+
const Column &column=col_iter->second;
-
+
out << std::setprecision(column.precision);
if (col_iter->second.scientific)
else
out.setf(std::ios::fixed, std::ios::floatfield);
out << std::setw(column_widths[j]);
- column.entries[i]->write_text(out);
+ out << column.entries[i].value;
out << " ";
}
out << std::endl;
out << "\\documentclass[10pt]{report}" << std::endl
<< "\\usepackage{float}" << std::endl << std::endl << std::endl
<< "\\begin{document}" << std::endl;
-
+
out << "\\begin{table}[H]" << std::endl
<< "\\begin{center}" << std::endl
<< "\\begin{tabular}{|";
{
std::string key=column_order[j];
// avoid `supercolumns[key]'
- const std::map<std::string, std::vector<std::string> >::const_iterator
+ const std::map<std::string, std::vector<std::string> >::const_iterator
super_iter=supercolumns.find(key);
if (super_iter!=supercolumns.end())
const std::map<std::string, Column>::const_iterator
col_iter=columns.find(super_iter->second[k]);
Assert(col_iter!=columns.end(), ExcInternalError());
-
+
out << col_iter->second.tex_format << "|";
}
}
out << "} \\hline" << std::endl;
// write the caption line of the table
-
+
for (unsigned int j=0; j<column_order.size(); ++j)
{
std::string key=column_order[j];
- const std::map<std::string, std::vector<std::string> >::const_iterator
+ const std::map<std::string, std::vector<std::string> >::const_iterator
super_iter=supercolumns.find(key);
if (super_iter!=supercolumns.end())
{
const unsigned int n_subcolumns=super_iter->second.size();
// avoid use of `tex_supercaptions[key]'
- std::map<std::string,std::string>::const_iterator
+ std::map<std::string,std::string>::const_iterator
tex_super_cap_iter=tex_supercaptions.find(key);
- out << std::endl << "\\multicolumn{" << n_subcolumns << "}{|c|}{"
+ out << std::endl << "\\multicolumn{" << n_subcolumns << "}{|c|}{"
<< tex_super_cap_iter->second << "}";
}
else
for (unsigned int i=0; i<nrows; ++i)
{
const unsigned int n_cols=sel_columns.size();
-
+
for (unsigned int j=0; j<n_cols; ++j)
{
std::string key=sel_columns[j];
const std::map<std::string, Column>::const_iterator
col_iter=columns.find(key);
Assert(col_iter!=columns.end(), ExcInternalError());
-
+
const Column &column=col_iter->second;
-
+
out << std::setprecision(column.precision);
if (col_iter->second.scientific)
out.setf(std::ios::scientific, std::ios::floatfield);
else
out.setf(std::ios::fixed, std::ios::floatfield);
-
- column.entries[i]->write_tex(out);
-
+
+ out << column.entries[i].value;
+
if (j<n_cols-1)
out << " & ";
}
std::string first_name=col_iter->first;
for (++col_iter; col_iter!=columns.end(); ++col_iter)
- Assert(col_iter->second.entries.size()==n,
- ExcWrongNumberOfDataEntries(col_iter->first,
- col_iter->second.entries.size(),
+ Assert(col_iter->second.entries.size()==n,
+ ExcWrongNumberOfDataEntries(col_iter->first,
+ col_iter->second.entries.size(),
first_name, n));
return n;
void TableHandler::get_selected_columns(std::vector<std::string> &sel_columns) const
{
sel_columns.clear();
-
+
for (unsigned int j=0; j<column_order.size(); ++j)
{
std::string key=column_order[j];
- const std::map<std::string, std::vector<std::string> >::const_iterator
+ const std::map<std::string, std::vector<std::string> >::const_iterator
super_iter=supercolumns.find(key);
if (super_iter!=supercolumns.end())
// explicit instantiations
-template class TableEntry<double>;
-template class TableEntry<float>;
-template class TableEntry<int>;
-template class TableEntry<unsigned int>;
-template class TableEntry<std::string>;
-
-
template
void TableHandler::add_value<double> (const std::string &,
const double);