1 | /* |
2 | * CSVWriter.hpp |
3 | * |
4 | * Created on: Dec 15, 2014 |
5 | * Author: Pietro Incardona |
6 | */ |
7 | |
8 | #ifndef CSVWRITER_HPP_ |
9 | #define CSVWRITER_HPP_ |
10 | |
11 | #include <iostream> |
12 | #include <boost/fusion/include/mpl.hpp> |
13 | #include <boost/fusion/include/for_each.hpp> |
14 | #include <fstream> |
15 | #include "util/common.hpp" |
16 | #include <boost/mpl/range_c.hpp> |
17 | #include "util/for_each_ref_host.hpp" |
18 | #include "csv_multiarray.hpp" |
19 | #include "util/util.hpp" |
20 | #include "is_csv_writable.hpp" |
21 | |
22 | #define CSV_WRITER 0x30000 |
23 | |
24 | /*! \brief this class is a functor for "for_each" algorithm |
25 | * |
26 | * For each element of the boost::vector the operator() is called. |
27 | * Is mainly used to create a string containing all the properties of the object |
28 | * |
29 | * \tparam Tobj object |
30 | * |
31 | */ |
32 | |
33 | template<typename Tobj> |
34 | struct csv_prp |
35 | { |
36 | //! String containing the csv line constructed from an object |
37 | std::stringstream & str; |
38 | |
39 | //! Object to write |
40 | Tobj & obj; |
41 | |
42 | /*! \brief Constructor |
43 | * |
44 | * Create a vertex properties list |
45 | * |
46 | * \param str streamstring |
47 | * \param obj object to write |
48 | * |
49 | */ |
50 | csv_prp(std::stringstream & str, Tobj & obj) |
51 | :str(str),obj(obj) |
52 | { |
53 | }; |
54 | |
55 | //! It call the functor for each member |
56 | template<typename T> |
57 | void operator()(T& t) |
58 | { |
59 | // This is the type of the csv column |
60 | typedef typename boost::mpl::at<typename Tobj::type,T>::type col_type; |
61 | |
62 | // Remove the reference from the column type |
63 | typedef typename boost::remove_reference<col_type>::type col_rtype; |
64 | typedef typename std::remove_all_extents<col_rtype>::type base_col_rtype; |
65 | |
66 | csv_value_str<col_rtype, is_csv_writable<base_col_rtype>::value >(obj.template get<T::value>(),str); |
67 | } |
68 | }; |
69 | |
70 | /*! \brief this class is a functor for "for_each" algorithm |
71 | * |
72 | * For each element of the boost::vector the operator() is called. |
73 | * Is mainly used to create a string containing all the properties of the object |
74 | * |
75 | * \tparam T object |
76 | * |
77 | */ |
78 | |
79 | template<typename Tobj, bool attr> |
80 | struct csv_col |
81 | { |
82 | //! String containing the colums list as string |
83 | std::stringstream & str; |
84 | |
85 | /*! \brief Constructor |
86 | * |
87 | * \str String where to put the colum list |
88 | * |
89 | */ |
90 | csv_col(std::stringstream & str) |
91 | :str(str) |
92 | { |
93 | }; |
94 | |
95 | //! It call the functor for each member |
96 | template<typename T> |
97 | inline void operator()(T& t) |
98 | { |
99 | // This is the type of the csv column |
100 | typedef typename boost::mpl::at<typename Tobj::type,boost::mpl::int_<T::value>>::type col_type; |
101 | |
102 | csv_col_str<col_type>(std::string(Tobj::attributes::name[T::value]),str); |
103 | } |
104 | }; |
105 | |
106 | /*! \brief this class is a functor for "for_each" algorithm |
107 | * |
108 | * This class is a functor for "for_each" algorithm. For each |
109 | * element of the boost::vector the operator() is called. |
110 | * Is mainly used to create a string containing all the vertex |
111 | * properties |
112 | * |
113 | * Specialization when we do not have vertex attributes |
114 | * |
115 | * \tparam G graph type |
116 | * |
117 | */ |
118 | |
119 | template<typename Tobj> |
120 | struct csv_col<Tobj,false> |
121 | { |
122 | //! String containing the colums list as string |
123 | std::stringstream & str; |
124 | |
125 | /*! \brief Constructor |
126 | * |
127 | * \str String where to put the colum list |
128 | * |
129 | */ |
130 | csv_col(std::stringstream & str) |
131 | :str(str) |
132 | { |
133 | }; |
134 | |
135 | //! It call the functor for each member |
136 | template<typename T> |
137 | void operator()(T& t) |
138 | { |
139 | // This is the type of the csv column |
140 | typedef typename boost::fusion::result_of::at_c<typename Tobj::type,T::value>::type col_type; |
141 | |
142 | // Remove the reference from the column type |
143 | typedef typename boost::remove_reference<col_type>::type col_rtype; |
144 | |
145 | std::stringstream str2; |
146 | str2 << "column_" << T::value; |
147 | |
148 | csv_col_str<col_rtype>(str2.str(),str); |
149 | } |
150 | }; |
151 | |
152 | #define VECTOR 1 |
153 | |
154 | /*! \brief CSV Writer |
155 | * |
156 | * It write in CSV format vector of objects living into an N-dimensional space |
157 | * |
158 | * \tparam v_pos Positional vector |
159 | * \tparam v_prp Property vector |
160 | * |
161 | */ |
162 | template <typename v_pos, typename v_prp, unsigned int impl = VECTOR> |
163 | class CSVWriter |
164 | { |
165 | /*! \brief Get the colums name (also the positional name) |
166 | * |
167 | */ |
168 | std::string get_csv_colums() |
169 | { |
170 | std::stringstream str; |
171 | |
172 | // write positional columns |
173 | for (size_t i = 0 ; i < v_pos::value_type::dims ; i++) |
174 | { |
175 | if (i == 0) |
176 | str << "x[" << i << "]" ; |
177 | else |
178 | str << "," << "x[" << i << "]" ; |
179 | } |
180 | |
181 | // write positional information |
182 | |
183 | csv_col<typename v_prp::value_type,has_attributes<typename v_prp::value_type>::value> col(str); |
184 | |
185 | // Iterate through all the vertex and create the vertex list |
186 | boost::mpl::for_each_ref_host< boost::mpl::range_c<int,0,v_prp::value_type::max_prop> >(col); |
187 | |
188 | str << "\n" ; |
189 | |
190 | return str.str(); |
191 | } |
192 | |
193 | /*! \brief Get the csv data section |
194 | * |
195 | * \param vp vector that contain the positional information |
196 | * \param vpr vector that contain the property information |
197 | * \param offset from where to start |
198 | * |
199 | */ |
200 | std::string get_csv_data(v_pos & vp, v_prp & vpr, size_t offset) |
201 | { |
202 | std::stringstream str; |
203 | |
204 | // The position and property vector size must match |
205 | if (vp.size() != vpr.size()) |
206 | { |
207 | std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " position vector and property vector must have the same size \n" ; |
208 | return std::string("" ); |
209 | } |
210 | |
211 | // Write the data |
212 | for (size_t i = offset ; i < vp.size() ; i++) |
213 | { |
214 | for (size_t j = 0 ; j < v_pos::value_type::dims ; j++) |
215 | { |
216 | if (j == 0) |
217 | str << vp.template get<0>(i)[j]; |
218 | else |
219 | str << "," << vp.template get<0>(i)[j]; |
220 | } |
221 | |
222 | // Object to write |
223 | auto obj = vpr.get(i); |
224 | |
225 | csv_prp<decltype(obj)> c_prp(str,obj); |
226 | |
227 | // write the properties to the stream string |
228 | boost::mpl::for_each_ref_host< boost::mpl::range_c<int,0,v_prp::value_type::max_prop> >(c_prp); |
229 | |
230 | str << "\n" ; |
231 | } |
232 | |
233 | return str.str(); |
234 | } |
235 | |
236 | public: |
237 | |
238 | /*! \brief It write a CSV file |
239 | * |
240 | * \tparam prp which properties to output [default = -1 (all)] |
241 | * |
242 | * \param file path where to write |
243 | * \param v positional vector |
244 | * \param prp properties vector |
245 | * \param offset from where to start to write |
246 | * |
247 | */ |
248 | bool write(std::string file, v_pos & v , v_prp & prp, size_t offset=0) |
249 | { |
250 | // Header for csv (colums name) |
251 | std::string ; |
252 | // Data point |
253 | std::string point_data; |
254 | |
255 | // Get csv columns |
256 | csv_header = get_csv_colums(); |
257 | |
258 | // For each property in the vertex type produce a point data |
259 | point_data = get_csv_data(v,prp,offset); |
260 | |
261 | // write the file |
262 | std::ofstream ofs(file); |
263 | |
264 | // Check if the file is open |
265 | if (ofs.is_open() == false) |
266 | {std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " cannot create the CSV file: " << file << std::endl;} |
267 | |
268 | ofs << csv_header << point_data; |
269 | |
270 | // Close the file |
271 | |
272 | ofs.close(); |
273 | |
274 | // Completed succefully |
275 | return true; |
276 | } |
277 | }; |
278 | |
279 | |
280 | #endif /* CSVWRITER_HPP_ */ |
281 | |
282 | |