CsvTableReader.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "CsvTableReader.H"
27 #include "DynamicList.H"
28 #include "Field.H"
29 
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34 namespace TableReaders
35 {
36 
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 
39 template<class Type>
41 (
42  const typename CsvLabelType<Type>::type& columns,
43  const List<string>& split
44 )
45 {
46  Type result;
47 
48  for (label i = 0; i < pTraits<Type>::nComponents; i++)
49  {
50  if (component(columns, i) >= split.size())
51  {
53  << "No column " << component(columns, i) << " in "
54  << split << endl
55  << exit(FatalError);
56  }
57 
58  result[i] = readScalar
59  (
60  IStringStream(split[component(columns, i)])()
61  );
62  }
63 
64  return result;
65 }
66 
67 
68 template<>
70 (
71  const typename CsvLabelType<scalar>::type& columns,
72  const List<string>& split
73 )
74 {
75  if (component(columns, 0) >= split.size())
76  {
78  << "No column " << component(columns, 0) << " in "
79  << split << endl
80  << exit(FatalError);
81  }
82 
83  return readLabel(IStringStream(split[component(columns, 0)])());
84 }
85 
86 template<>
87 inline scalar CsvReadValue<scalar>
88 (
89  const typename CsvLabelType<scalar>::type& columns,
90  const List<string>& split
91 )
92 {
93  if (component(columns, 0) >= split.size())
94  {
96  << "No column " << component(columns, 0) << " in "
97  << split << endl
98  << exit(FatalError);
99  }
100 
101  return readScalar(IStringStream(split[component(columns, 0)])());
102 }
103 
104 
105 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
106 
107 } // End namespace TableReaders
108 } // End namespace Foam
109 
110 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
111 
112 template<class Coordinate, class Value>
114 (
115  ISstream& is,
116  List<Tuple2<Coordinate, Value>>& data
117 ) const
118 {
119  DynamicList<Tuple2<Coordinate, Value>> values;
120 
121  // Skip header
122  for (label i = 0; i < nHeaderLine_; i++)
123  {
124  string line;
125  is.getLine(line);
126  }
127 
128  const label nEntries =
129  max(cmptMax(columns_.first()), cmptMax(columns_.second()));
130 
131  // Read data
132  while (is.good())
133  {
134  string line;
135  is.getLine(line);
136 
137  label n = 0;
138  std::size_t pos = 0;
139  DynamicList<string> split;
140 
141  if (mergeSeparators_)
142  {
143  std::size_t nPos = 0;
144 
145  while ((pos != std::string::npos) && (n <= nEntries))
146  {
147  bool found = false;
148  while (!found)
149  {
150  nPos = line.find(separator_, pos);
151 
152  if ((nPos != std::string::npos) && (nPos - pos == 0))
153  {
154  pos = nPos + 1;
155  }
156  else
157  {
158  found = true;
159  }
160  }
161 
162  nPos = line.find(separator_, pos);
163 
164  if (nPos == std::string::npos)
165  {
166  split.append(line.substr(pos));
167  pos = nPos;
168  n++;
169  }
170  else
171  {
172  split.append(line.substr(pos, nPos - pos));
173  pos = nPos + 1;
174  n++;
175  }
176  }
177  }
178  else
179  {
180  while ((pos != std::string::npos) && (n <= nEntries))
181  {
182  std::size_t nPos = line.find(separator_, pos);
183 
184  if (nPos == std::string::npos)
185  {
186  split.append(line.substr(pos));
187  pos = nPos;
188  n++;
189  }
190  else
191  {
192  split.append(line.substr(pos, nPos - pos));
193  pos = nPos + 1;
194  n++;
195  }
196  }
197  }
198 
199  if (split.size() <= 1)
200  {
201  break;
202  }
203 
204  values.append
205  (
206  Tuple2<Coordinate , Value>
207  (
208  CsvReadValue<Coordinate>(columns_.first(), split),
209  CsvReadValue<Value>(columns_.second(), split)
210  )
211  );
212  }
213 
214  data.transfer(values);
215 }
216 
217 
218 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
219 
220 template<class Coordinate, class Value>
222 (
223  const word& name,
224  const Function1s::unitSets& units,
225  const dictionary& dict
226 )
227 :
228  TableFileReader<Coordinate, Value>(units, dict),
229  nHeaderLine_(dict.lookup<label>("nHeaderLine")),
230  columns_
231  (
232  dict.found("column")
233  ? columnIndices(dict.lookup("columns"))
234  : dict.found("refColumn") || dict.found("componentColumns")
235  ? columnIndices
236  (
237  CsvLabelType<Coordinate>()
238  (
239  dict.lookup<typename CsvLabelType<Coordinate>::oldType>
240  (
241  "refColumn"
242  )
243  ),
244  CsvLabelType<Value>()
245  (
246  dict.lookup<typename CsvLabelType<Value>::oldType>
247  (
248  "componentColumns"
249  )
250  )
251  )
252  : columnIndices(dict.lookup("columns"))
253  ),
254  separator_(dict.lookupOrDefault<string>("separator", string(","))[0]),
255  mergeSeparators_(readBool(dict.lookup("mergeSeparators")))
256 {}
257 
258 
259 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
260 
261 template<class Coordinate, class Value>
263 {}
264 
265 
266 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
267 
268 template<class Coordinate, class Value>
270 (
271  Ostream& os,
272  const Function1s::unitSets& units,
274  const word&
275 ) const
276 {
278 
279  writeEntry(os, "nHeaderLine", nHeaderLine_);
280  writeEntry(os, "columns", columns_);
281  writeEntry(os, "separator", string(separator_));
282  writeEntry(os, "mergeSeparators", mergeSeparators_);
283 }
284 
285 
286 // ************************************************************************* //
bool found
label n
Input from memory buffer stream.
Definition: IStringStream.H:52
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
Base class to read table data for tables.
virtual void write(Ostream &os, const Function1s::unitSets &units, const List< Tuple2< Coordinate, Value >> &table, const word &valuesKeyword=word::null) const
Write additional information.
Reads an interpolation table from a file in CSV-format. Entries govern the layout of the CSV file....
virtual ~Csv()
Destructor.
virtual void write(Ostream &os, const Function1s::unitSets &units, const List< Tuple2< Coordinate, Value >> &table, const word &valuesKeyword=word::null) const
Write settings and values.
Csv(const word &name, const Function1s::unitSets &units, const dictionary &dict)
Construct from name and dictionary.
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:66
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Motion of the mesh specified as a list of pointMeshMovers.
A class for handling character strings derived from std::string.
Definition: string.H:79
A class for handling words, derived from string.
Definition: word.H:63
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
scalar CsvReadValue< scalar >(const typename CsvLabelType< scalar >::type &columns, const List< string > &split)
label CsvReadValue< label >(const typename CsvLabelType< scalar >::type &columns, const List< string > &split)
Type CsvReadValue(const typename CsvLabelType< Type >::type &columns, const List< string > &split)
const HashTable< dimensionSet > table
Table of dimensions.
Definition: dimensions.C:74
const unitSet & lookup(const word &unitName)
Lookup and return the named unit from the table.
Definition: units.C:346
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dimensionedScalar pos(const dimensionedScalar &ds)
bool readBool(Istream &)
Definition: boolIO.C:63
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
void cmptMax(Field< typename Field< Type >::cmptType > &res, const UList< Type > &f)
void component(GeometricField< typename GeometricField< Type, GeoMesh, PrimitiveField1 >::cmptType, GeoMesh, PrimitiveField1 > &gcf, const GeometricField< Type, GeoMesh, PrimitiveField2 > &gf, const direction d)
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if successful.
Definition: doubleScalar.H:75
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
label readLabel(Istream &is)
Definition: label.H:64
error FatalError
void writeEntry(Ostream &os, const word &key, const DimensionedFieldFunction< DimensionedFieldType > &f)
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dictionary dict
Struct containing two unitSets for use in converting both the argument and the value of a Function1.