Alexandria  2.14.1
Please provide a description of the project.
AsciiWriter.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2020 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
25 #include <fstream>
26 #include <sstream>
27 #include <boost/lexical_cast.hpp>
29 #include "Table/AsciiWriter.h"
30 #include "AsciiWriterHelper.h"
31 
32 namespace Euclid {
33 namespace Table {
34 
35 AsciiWriter::AsciiWriter(std::ostream& stream) : AsciiWriter(InstOrRefHolder<std::ostream>::create(stream)) {
36 }
37 
38 AsciiWriter::AsciiWriter(const std::string& filename) : AsciiWriter(create<std::ofstream>(filename)) {
39 }
40 
42  : m_stream_holder(std::move(stream_holder)) {
43 }
44 
46  if (m_writing_started) {
47  throw Elements::Exception() << "Changing comment indicator after writing "
48  << "has started is not allowed";
49  }
50  if (indicator.empty()) {
51  throw Elements::Exception() << "Empty string as comment indicator";
52  }
53  m_comment = indicator;
54  return *this;
55 }
56 
58  if (m_writing_started) {
59  throw Elements::Exception() << "Changing column info visibility after writing "
60  << "has started is not allowed";
61  }
62  m_show_column_info = show;
63  return *this;
64 }
65 
66 void AsciiWriter::addComment(const std::string& message) {
67  if (m_initialized) {
68  throw Elements::Exception() << "Adding comments after writing data in ASCII "
69  << "format is not allowed";
70  }
71  m_writing_started = true;
72 
73  std::stringstream message_stream {message};
74  while (!message_stream.eof()) {
75  std::string line;
76  std::getline(message_stream, line);
77  m_stream_holder->ref() << m_comment << ' ' << line << '\n';
78  }
79 }
80 
81 void AsciiWriter::init(const Table& table) {
82  m_initialized = true;
83  // If we have already written anything we leave an empty line
84  if (m_writing_started) {
85  m_stream_holder->ref() << '\n';
86  }
87  m_writing_started = true;
88 
89  auto& out = m_stream_holder->ref();
90 
91  // Write the column descriptions
92  auto& info = *table.getColumnInfo();
93  if (m_show_column_info) {
94  for (size_t i=0; i<info.size(); ++i) {
95  auto& desc = info.getDescription(i);
96  out << m_comment << " Column: " << desc.name << ' ' << typeToKeyword(desc.type);
97  if (!desc.unit.empty()) {
98  out << " (" << desc.unit << ")";
99  }
100  if (!desc.description.empty()) {
101  out << " - " << desc.description;
102  }
103  out << '\n';
104  }
105  out << '\n';
106  }
107 
108  // Write the column names
109  auto column_lengths = calculateColumnLengths(table);
110  out << m_comment.c_str();
111  for (size_t i=0; i<info.size(); ++i) {
112  out << std::setw(column_lengths[i]) << info.getDescription(i).name;
113  }
114  out << "\n\n";
115 }
116 
117 void AsciiWriter::append(const Table& table) {
118  auto& out = m_stream_holder->ref();
119  auto column_lengths = calculateColumnLengths(table);
120  // The data lines are not prefixed with the comment string, so we need to fix
121  // the length of the first column to get the alignment correctly
122  column_lengths[0] = column_lengths[0] + m_comment.size();
123  for (auto row : table) {
124  for (size_t i=0; i<row.size(); ++i) {
125  out << std::setw(column_lengths[i]) << boost::lexical_cast<std::string>(row[i]);
126  }
127  out << "\n";
128  }
129 }
130 
131 
132 } // Table namespace
133 } // Euclid namespace
134 
135 
136 
T empty(T... args)
TableWriter implementation for writing ASCII tables to streams.
Definition: AsciiWriter.h:80
AsciiWriter & showColumnInfo(bool show)
Sets if the column information will be written to the stream.
Definition: AsciiWriter.cpp:57
AsciiWriter(std::ostream &stream)
Constructs an AsciiWriter which writes to the given stream.
Definition: AsciiWriter.cpp:35
T getline(T... args)
void addComment(const std::string &message) override
Adds a comment to the stream.
Definition: AsciiWriter.cpp:66
STL namespace.
T setw(T... args)
STL class.
void append(const Table &table) override
std::string typeToKeyword(std::type_index type)
Converts a type to its string representation.
Represents a table.
Definition: Table.h:49
T size(T... args)
STL class.
T c_str(T... args)
void init(const Table &table) override
Definition: AsciiWriter.cpp:81
AsciiWriter & setCommentIndicator(const std::string &indicator)
Set the comment indicator.
Definition: AsciiWriter.cpp:45
std::vector< size_t > calculateColumnLengths(const Table &table)
Calculates the sizes in characters each column of the table needs.
STL class.
std::unique_ptr< InstOrRefHolder< std::ostream > > m_stream_holder
Definition: AsciiWriter.h:183