// (C) Copyright 2008-2009 SDML (www.sdml.info) // // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // Copyright Andrew Sutton 2007 // // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_FCA_WRITE_TABLE_HPP #define BOOST_FCA_WRITE_TABLE_HPP #include #include #include #include #include namespace boost { namespace fca { template void write_table(std::ostream& os, const Relation& rel) { using namespace std; using namespace boost; typedef typename Relation::context_type Context; typedef typename Relation::object_type Object; typedef typename Relation::object_set ObjectSet; typedef typename ObjectSet::const_iterator ObjectIterator; typedef typename Relation::attribute_type Attribute; typedef typename Relation::attribute_set AttributeSet; typedef typename AttributeSet::const_iterator AttributeIterator; typedef std::vector StringVector; typedef std::vector SizeVector; const Context& cxt = rel.context(); // Create a vector to store the width of each column - note the // first column stores objects. StringVector onames(cxt.num_objects()); SizeVector sizes(1, 0); // This is actually a fairly tedious little algorithm because we have // to correctly size the outputs. Start by iterative over the objects // in order to find the max-with'd name there. ObjectIterator o, o_end = cxt.objects().end(); for(o = cxt.objects().begin(); o != o_end; ++o) { const Object& obj = *o; // Write this into a string so we can get the length of it. Note // that Object must be output-streamable. stringstream ss; ss << obj; onames.push_back(ss.str()); // Is this the longest string? if(onames.back().size() > sizes[0]) { sizes[0] = onames.back().size(); } } // Star the printing! First, we need to write out the headers. This // includes all attributes. os << setw(sizes[0]) << " " << "|"; AttributeIterator a, a_end = cxt.attributes().end(); for(a = cxt.attributes().begin(); a != a_end; ++a) { stringstream ss; ss << *a; // Add this the size to the array of sizes and write the header./ string att = ss.str(); sizes.push_back(att.size()); os << setw(sizes.back()) << att << "|"; } os << endl; // Write out each row in the table. for(o = cxt.objects().begin(); o != o_end; ++o) { os << setw(sizes[0]) << *o << "|"; // Iterate over the atts for each object and write an X if the // attribute exists or nothing if it doesn't. int x = 1; for(a = cxt.attributes().begin(); a != a_end; ++a, ++x) { os << setw(sizes[x]) << (rel.test(*o, *a) ? "X" : " ") << "|"; } os << endl; } os << endl; } } /* namespace fca */ } /* namespace boost */ #endif