10#ifndef XTENSOR_CSV_HPP
11#define XTENSOR_CSV_HPP
19#include "../containers/xtensor.hpp"
20#include "../core/xtensor_config.hpp"
29 template <
class T,
class A = std::allocator<T>>
32 template <
class T,
class A = std::allocator<T>>
35 const char delimiter =
',',
36 const std::size_t skip_rows = 0,
37 const std::ptrdiff_t max_rows = -1,
38 const std::string comments =
"#"
51 inline T lexical_cast(
const std::string& cell)
54 std::istringstream iss(cell);
60 inline std::string lexical_cast(
const std::string& cell)
62 size_t first = cell.find_first_not_of(
' ');
63 if (first == std::string::npos)
68 size_t last = cell.find_last_not_of(
' ');
69 return cell.substr(first, last == std::string::npos ? cell.size() : last - first + 1);
73 inline float lexical_cast<float>(
const std::string& cell)
75 return std::stof(cell);
79 inline double lexical_cast<double>(
const std::string& cell)
81 return std::stod(cell);
85 inline long double lexical_cast<long double>(
const std::string& cell)
87 return std::stold(cell);
91 inline int lexical_cast<int>(
const std::string& cell)
93 return std::stoi(cell);
97 inline signed char lexical_cast<signed char>(
const std::string& cell)
99 return static_cast<signed char>(std::stoi(cell));
103 inline unsigned char lexical_cast<unsigned char>(
const std::string& cell)
105 return static_cast<unsigned char>(std::stoul(cell));
109 inline long lexical_cast<long>(
const std::string& cell)
111 return std::stol(cell);
115 inline long long lexical_cast<long long>(
const std::string& cell)
117 return std::stoll(cell);
121 inline unsigned int lexical_cast<unsigned int>(
const std::string& cell)
123 return static_cast<unsigned int>(std::stoul(cell));
127 inline unsigned long lexical_cast<unsigned long>(
const std::string& cell)
129 return std::stoul(cell);
133 inline unsigned long long lexical_cast<unsigned long long>(
const std::string& cell)
135 return std::stoull(cell);
138 template <
class ST,
class T,
class OI>
139 ST load_csv_row(std::istream& row_stream, OI output, std::string cell,
const char delimiter =
',')
142 while (std::getline(row_stream, cell, delimiter))
144 *output++ = lexical_cast<T>(cell);
162 template <
class T,
class A>
164 std::istream& stream,
165 const char delimiter,
166 const std::size_t skip_rows,
167 const std::ptrdiff_t max_rows,
168 const std::string comments
171 using tensor_type = xcsv_tensor<T, A>;
172 using storage_type =
typename tensor_type::storage_type;
173 using size_type =
typename tensor_type::size_type;
174 using inner_shape_type =
typename tensor_type::inner_shape_type;
175 using inner_strides_type =
typename tensor_type::inner_strides_type;
176 using output_iterator = std::back_insert_iterator<storage_type>;
179 size_type nbrow = 0, nbcol = 0, nhead = 0;
181 output_iterator output(data);
182 std::string
row, cell;
183 while (std::getline(stream,
row))
185 if (nhead < skip_rows)
190 if (std::equal(comments.begin(), comments.end(),
row.begin()))
194 if (0 < max_rows && max_rows <=
static_cast<const long long>(nbrow))
198 std::stringstream row_stream(
row);
199 nbcol = detail::load_csv_row<size_type, T, output_iterator>(row_stream, output, cell, delimiter);
203 inner_shape_type shape = {nbrow, nbcol};
207 if (data.size() != data_size)
209 XTENSOR_THROW(std::runtime_error,
"Inconsistent row lengths in CSV");
211 return tensor_type(std::move(data), std::move(shape), std::move(
strides));
223 using size_type =
typename E::size_type;
225 if (ex.dimension() == 1)
227 const size_type n = ex.shape()[0];
228 for (size_type i = 0; i != n; ++i)
238 else if (ex.dimension() == 2)
240 const size_type nbrows = ex.shape()[0];
241 const size_type nbcols = ex.shape()[1];
242 for (size_type r = 0; r != nbrows; ++r)
244 for (size_type c = 0; c != nbcols; ++c)
257 XTENSOR_THROW(std::runtime_error,
"Only 1-D and 2-D expressions can be serialized to CSV");
264 std::size_t skip_rows;
265 std::ptrdiff_t max_rows;
266 std::string comments;
280 using size_type =
typename E::size_type;
282 if (ex.dimension() == 1)
284 const size_type n = ex.shape()[0];
285 for (size_type i = 0; i != n; ++i)
290 stream << config.delimiter;
295 else if (ex.dimension() == 2)
297 const size_type nbrows = ex.shape()[0];
298 const size_type nbcols = ex.shape()[1];
299 for (size_type r = 0; r != nbrows; ++r)
301 for (size_type c = 0; c != nbcols; ++c)
306 stream << config.delimiter;
314 XTENSOR_THROW(std::runtime_error,
"Only 1-D and 2-D expressions can be serialized to CSV");
Base class for xexpressions.
derived_type & derived_cast() &noexcept
Returns a reference to the actual derived type of the xexpression.
Dense multidimensional container with tensor semantic and fixed dimension.
std::size_t compute_strides(const shape_type &shape, layout_type l, strides_type &strides)
Compute the strides given the shape and the layout of an array.
auto strides(const E &e, stride_type type=stride_type::normal) noexcept
Get strides of an object.
standard mathematical functions for xexpressions
xcsv_tensor< T, A > load_csv(std::istream &stream, const char delimiter=',', const std::size_t skip_rows=0, const std::ptrdiff_t max_rows=-1, const std::string comments="#")
Load tensor from CSV.
auto row(E &&e, std::ptrdiff_t index)
Constructs and returns a row (sliced view) on the specified expression.
void dump_csv(std::ostream &stream, const xexpression< E > &e)
Dump tensor to CSV.