Loading...
Searching...
No Matches
CSV.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2016-2023 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "CSV.H"
30#include "DynamicList.H"
31#include "ListOps.H"
32
33// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
34
35template<class Type>
36Foam::labelList Foam::Function1Types::CSV<Type>::getComponentColumns
37(
38 const word& name,
39 const dictionary& dict
40)
41{
42 // Writing of columns was forced to be ASCII,
43 // do the same when reading
44
45 labelList cols;
46
47 ITstream& is = dict.lookup(name);
48 is.format(IOstreamOption::ASCII);
49 is >> cols;
50 dict.checkITstream(is, name);
51
52 if (cols.size() != pTraits<Type>::nComponents)
53 {
55 << name << " with " << cols
56 << " does not have the expected length "
57 << pTraits<Type>::nComponents << nl
58 << exit(FatalIOError);
59 }
60
61 return cols;
62}
63
64
65// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
66
67template<class Type>
68Type Foam::Function1Types::CSV<Type>::readValue
69(
70 const UList<string>& strings
71) const
72{
73 Type result;
74
75 if constexpr (std::is_integral_v<Type>)
76 {
77 // nComponents == 1
78 setComponent(result, 0) = readLabel(strings[componentColumns_[0]]);
79 }
80 else
81 {
82 for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; ++cmpt)
83 {
84 setComponent(result, cmpt) =
85 readScalar(strings[componentColumns_[cmpt]]);
86 }
87 }
88
89 return result;
90}
91
92
93template<class Type>
94void Foam::Function1Types::CSV<Type>::read()
95{
96 fileName expandedFile(fName_);
97 autoPtr<ISstream> isPtr(fileHandler().NewIFstream(expandedFile.expand()));
98 ISstream& is = isPtr();
99
100 if (!is.good())
101 {
103 << "Cannot open CSV file for reading."
104 << exit(FatalIOError);
105 }
106
107 const label maxEntry =
108 max(refColumn_, componentColumns_[findMax(componentColumns_)]);
109
110 string line;
111 label lineNo = 0;
112
113 // Skip header
114 for (label i = 0; i < nHeaderLine_; ++i)
115 {
116 is.getLine(nullptr);
117 ++lineNo;
118 }
119
120 DynamicList<Tuple2<scalar, Type>> values;
121 DynamicList<string> strings(maxEntry+1); // reserve
122
123 while (is.good())
124 {
125 is.getLine(line);
126 ++lineNo;
127
128 strings.clear();
129
130 std::size_t pos = 0;
131
132 for
133 (
134 label n = 0;
135 (pos != std::string::npos) && (n <= maxEntry);
136 ++n
137 )
138 {
139 if (mergeSeparators_)
140 {
141 bool found = false;
142 while (!found)
143 {
144 const auto nPos = line.find(separator_, pos);
145
146 if ((nPos != std::string::npos) && (nPos - pos == 0))
147 {
148 pos = nPos + 1;
149 }
150 else
151 {
152 found = true;
153 }
154 }
155 }
156
157 const auto nPos = line.find(separator_, pos);
158
159 if (nPos == std::string::npos)
160 {
161 strings.push_back(line.substr(pos));
162 pos = nPos;
163 }
164 else
165 {
166 strings.push_back(line.substr(pos, nPos - pos));
167 pos = nPos + 1;
168 }
169 }
170
171 if (strings.size() <= 1)
172 {
173 break;
174 }
175
176 if (strings.size() <= maxEntry)
177 {
179 << "Not enough columns near line " << lineNo
180 << ". Require " << (maxEntry+1) << " but found "
181 << strings << nl
182 << exit(FatalError);
183 }
184
185 scalar x = readScalar(strings[refColumn_]);
186 Type value = readValue(strings);
187
188 values.emplace_back(x, value);
189 }
190
191 this->table_.transfer(values);
192}
193
194
195// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
196
197template<class Type>
199(
200 const word& entryName,
201 const dictionary& dict,
202 const objectRegistry* obrPtr,
203 const fileName& fName
204)
205:
206 TableBase<Type>(entryName, dict, obrPtr),
207 nHeaderLine_(dict.get<label>("nHeaderLine")),
208 refColumn_(dict.get<label>("refColumn")),
209 componentColumns_(getComponentColumns("componentColumns", dict)),
210 separator_(dict.getOrDefault<string>("separator", ",")[0]),
211 mergeSeparators_(dict.get<bool>("mergeSeparators")),
212 fName_(fName.empty() ? dict.get<fileName>("file") : fName)
213{
214 read();
215
217}
218
219
220template<class Type>
222:
223 TableBase<Type>(csv),
224 nHeaderLine_(csv.nHeaderLine_),
225 refColumn_(csv.refColumn_),
226 componentColumns_(csv.componentColumns_),
227 separator_(csv.separator_),
228 mergeSeparators_(csv.mergeSeparators_),
229 fName_(csv.fName_)
230{}
231
232
233// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
234
235template<class Type>
237{
238 return fName_;
239}
240
241
242template<class Type>
244{
245 // Note: for TableBase write the dictionary entries it needs but not
246 // the values themselves
248
249 os.writeEntry("nHeaderLine", nHeaderLine_);
250 os.writeEntry("refColumn", refColumn_);
251
252 // Force writing labelList in ASCII
253 const auto oldFmt = os.format(IOstreamOption::ASCII);
254 os.writeEntry("componentColumns", componentColumns_);
255 os.format(oldFmt);
256
257 os.writeEntry("separator", string(separator_));
258 os.writeEntry("mergeSeparators", mergeSeparators_);
259 os.writeEntry("file", fName_);
260}
261
262
263template<class Type>
265{
267 os.endEntry();
268
269 os.beginBlock(word(this->name() + "Coeffs"));
270 writeEntries(os);
271 os.endBlock();
272}
273
274
275// ************************************************************************* //
Various functions to operate on Lists.
bool found
label n
Templated CSV function.
Definition CSV.H:74
CSV(const word &entryName, const dictionary &dict, const objectRegistry *obrPtr=nullptr, const fileName &fName=fileName::null)
Construct from entry name, dictionary and optional registry.
Definition CSV.C:192
virtual void writeData(Ostream &os) const
Write in dictionary format.
Definition CSV.C:257
virtual const fileName & fName() const
Return const access to the file name.
Definition CSV.C:229
virtual void writeEntries(Ostream &os) const
Write coefficient entries in dictionary format.
Definition CSV.C:236
Base class for table with bounds handling, interpolation and integration.
Definition TableBase.H:59
void initialise()
Check the table for size and consistency.
Definition TableBase.C:103
TableBase(const word &name, const dictionary &dict, const objectRegistry *obrPtr=nullptr)
Construct from dictionary - note table is not populated.
Definition TableBase.C:56
virtual void writeEntries(Ostream &os) const
Write keywords only in dictionary format.
Definition TableBase.C:341
List< Tuple2< scalar, Type > > table_
Table data.
Definition TableBase.H:77
virtual void writeData(Ostream &os) const
Write in dictionary format.
Definition Function1.C:156
@ ASCII
"ascii" (normal default)
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
A class for handling file names.
Definition fileName.H:75
Registry of regIOobjects.
A class for handling character strings derived from std::string.
Definition string.H:76
A class for handling words, derived from Foam::string.
Definition word.H:66
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
auto & name
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Definition HashOps.H:164
dimensionedScalar pos(const dimensionedScalar &ds)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< label > labelList
A List of labels.
Definition List.H:62
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler().
label & setComponent(label &val, const direction) noexcept
Non-const access to integer-type (has no components).
Definition label.H:160
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition label.H:63
label findMax(const ListType &input, label start=0)
Linear search for the index of the max element, similar to std::max_element but for lists and returns...
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
dictionary dict