NEML2 1.4.0
Loading...
Searching...
No Matches
Sequence.h
1// Copyright 2023, UChicago Argonne, LLC
2// All Rights Reserved
3// Software Name: NEML2 -- the New Engineering material Model Library, version 2
4// By: Argonne National Laboratory
5// OPEN SOURCE LICENSE (MIT)
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in
15// all copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23// THE SOFTWARE.
24
25#pragma once
26
27#include <vector>
28#include <string>
29
30#include "neml2/misc/parser_utils.h"
31#include "csvparser/csv.hpp"
32
33namespace neml2
34{
35// Forward decl
36template <typename T>
37class Sequence;
38template <typename T>
39std::stringstream & operator>>(std::stringstream &, Sequence<T> &);
40
60template <typename T>
62{
63public:
64 Sequence() = default;
65
71 Sequence<T> & operator=(const std::string & other);
72
74 operator std::vector<T>() const;
75
77 std::vector<T> vec() const;
78
80 bool operator==(const Sequence<T> & other) const { return _raw_str == other.raw(); }
81
83 const std::string & raw() const { return _raw_str; }
84
85 friend std::stringstream & operator>> <>(std::stringstream & in, Sequence<T> &);
86
87private:
89 std::string _raw_str;
90};
91} // namespace neml2
92
94// Implementations
96
97namespace neml2
98{
99template <typename T>
100Sequence<T> &
101Sequence<T>::operator=(const std::string & other)
102{
103 _raw_str = other;
104 return *this;
105}
106
107template <typename T>
108Sequence<T>::operator std::vector<T>() const
109{
110 return vec();
111}
112
113template <typename T>
114std::vector<T>
116{
117 // If the string is empty, just return an empty vector
118 if (_raw_str.empty())
119 return std::vector<T>();
120
121 // Parse into a vector of string, and if the vector has length greater than one, then this
122 // must be a vector instead of a CSV file column.
123 auto str_vec = utils::parse_vector<std::string>(_raw_str);
124 if (str_vec.size() > 1)
125 {
126 std::vector<T> v;
127 for (const auto & s : str_vec)
128 v.push_back(utils::parse<T>(s));
129 return v;
130 }
131
132 // If the string vector has exactly one element, we need to check if it conforms with our CSV
133 // file column schema
134
135 // Case 1: It doesn't conform the the CSV column schema, then just parse it normally
136 if (str_vec[0].find(".csv:") == std::string::npos)
137 return {utils::parse<T>(str_vec[0])};
138
139 // Case 2: Invoke the 3rd party csv reader
140 // Remove white space
141 const auto str_trimmed = utils::trim(_raw_str);
142
143 // Find file name and column identifier
144 const auto pos = str_trimmed.find(".csv:");
145 const auto filename = str_trimmed.substr(0, pos + 4);
146 const auto col_id = str_trimmed.substr(pos + 5);
147
148 std::vector<T> v;
149 try
150 {
151 // Open the CSV
152 csv::CSVReader reader(filename);
153
154 // Get the column index
155 int col;
156 if (col_id.front() == '[' && col_id.back() == ']')
157 col = utils::parse<int>(col_id.substr(1, col_id.length() - 2));
158 else
159 col = reader.index_of(col_id);
160
161 // Loop through rows to fill the vector
162 for (const auto & row : reader)
163 v.push_back(utils::parse<T>(row[col].get<std::string>()));
164 }
165 catch (std::exception & e)
166 {
167 throw NEMLException("The following error was thrown while reading the CSV column '" + _raw_str +
168 "':\n" + e.what());
169 }
170
171 return v;
172}
173
174template <typename T>
175std::ostream &
176operator<<(std::ostream & os, const Sequence<T> & seq)
177{
178 os << seq.raw();
179 return os;
180}
181
182template <typename T>
183std::stringstream &
184operator>>(std::stringstream & ss, Sequence<T> & seq)
185{
186 // This is special -- we have to eat the entire stream
187 seq._raw_str = ss.str();
188 ss.setstate(std::ios_base::eofbit);
189 return ss;
190}
191} // namespace neml2
The wrapper (decorator) for cross-referencing unresolved values at parse time.
Definition CrossRef.h:52
const std::string & raw() const
Get the raw string literal.
Definition CrossRef.h:79
CrossRef()=default
Definition error.h:33
A lazily parsed sequence of data.
Definition Sequence.h:62
std::vector< T > vec() const
Convert to a vector.
Definition Sequence.h:115
Sequence< T > & operator=(const std::string &other)
Assignment operator.
Definition Sequence.h:101
Sequence()=default
const std::string & raw() const
Get the raw string literal.
Definition Sequence.h:83
bool operator==(const Sequence< T > &other) const
Test equality.
Definition Sequence.h:80
std::string trim(const std::string &str, const std::string &white_space)
Definition parser_utils.cxx:76
Definition CrossRef.cxx:32
std::ostream & operator<<(std::ostream &os, const OptionCollection &p)
Definition OptionCollection.cxx:37
std::stringstream & operator>>(std::stringstream &, CrossRef< T > &)
Definition CrossRef.h:113