CSV.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-2019 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 "CSV.H"
27 #include "DynamicList.H"
28 
29 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
30 
31 template<>
33 (
34  const List<string>& split
35 )
36 {
37  if (componentColumns_[0] >= split.size())
38  {
40  << "No column " << componentColumns_[0] << " in "
41  << split << endl
42  << exit(FatalError);
43  }
44 
45  return readLabel(IStringStream(split[componentColumns_[0]])());
46 }
47 
48 
49 template<>
51 (
52  const List<string>& split
53 )
54 {
55  if (componentColumns_[0] >= split.size())
56  {
58  << "No column " << componentColumns_[0] << " in "
59  << split << endl
60  << exit(FatalError);
61  }
62 
63  return readScalar(IStringStream(split[componentColumns_[0]])());
64 }
65 
66 
67 template<class Type>
68 Type Foam::Function1Types::CSV<Type>::readValue(const List<string>& split)
69 {
70  Type result;
71 
72  for (label i = 0; i < pTraits<Type>::nComponents; i++)
73  {
74  if (componentColumns_[i] >= split.size())
75  {
77  << "No column " << componentColumns_[i] << " in "
78  << split << endl
79  << exit(FatalError);
80  }
81 
82  result[i] =
83  readScalar(IStringStream(split[componentColumns_[i]])());
84  }
85 
86  return result;
87 }
88 
89 
90 template<class Type>
92 {
93  fileName expandedFile(fName_);
94  autoPtr<ISstream> isPtr(fileHandler().NewIFstream(expandedFile.expand()));
95  ISstream& is = isPtr();
96 
97  if (!is.good())
98  {
100  << "Cannot open CSV file for reading."
101  << exit(FatalIOError);
102  }
103 
104  DynamicList<Tuple2<scalar, Type>> values;
105 
106  // Skip header
107  for (label i = 0; i < nHeaderLine_; i++)
108  {
109  string line;
110  is.getLine(line);
111  }
112 
113  const label nEntries = max(refColumn_, max(componentColumns_));
114 
115  // Read data
116  while (is.good())
117  {
118  string line;
119  is.getLine(line);
120 
121 
122  label n = 0;
123  std::size_t pos = 0;
124  DynamicList<string> split;
125 
126  if (mergeSeparators_)
127  {
128  std::size_t nPos = 0;
129 
130  while ((pos != std::string::npos) && (n <= nEntries))
131  {
132  bool found = false;
133  while (!found)
134  {
135  nPos = line.find(separator_, pos);
136 
137  if ((nPos != std::string::npos) && (nPos - pos == 0))
138  {
139  pos = nPos + 1;
140  }
141  else
142  {
143  found = true;
144  }
145  }
146 
147  nPos = line.find(separator_, pos);
148 
149  if (nPos == std::string::npos)
150  {
151  split.append(line.substr(pos));
152  pos = nPos;
153  n++;
154  }
155  else
156  {
157  split.append(line.substr(pos, nPos - pos));
158  pos = nPos + 1;
159  n++;
160  }
161  }
162  }
163  else
164  {
165  while ((pos != std::string::npos) && (n <= nEntries))
166  {
167  std::size_t nPos = line.find(separator_, pos);
168 
169  if (nPos == std::string::npos)
170  {
171  split.append(line.substr(pos));
172  pos = nPos;
173  n++;
174  }
175  else
176  {
177  split.append(line.substr(pos, nPos - pos));
178  pos = nPos + 1;
179  n++;
180  }
181  }
182  }
183 
184 
185  if (split.size() <= 1)
186  {
187  break;
188  }
189 
190  scalar x = readScalar(IStringStream(split[refColumn_])());
191  Type value = readValue(split);
192 
193  values.append(Tuple2<scalar,Type>(x, value));
194  }
195 
196  this->table_.transfer(values);
197 }
198 
199 
200 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
201 
202 template<class Type>
204 (
205  const word& entryName,
206  const dictionary& dict
207 )
208 :
209  TableBase<Type>(entryName, dict),
210  nHeaderLine_(readLabel(dict.lookup("nHeaderLine"))),
211  refColumn_(readLabel(dict.lookup("refColumn"))),
212  componentColumns_(dict.lookup("componentColumns")),
213  separator_(dict.lookupOrDefault<string>("separator", string(","))[0]),
214  mergeSeparators_(readBool(dict.lookup("mergeSeparators"))),
215  fName_(dict.lookup("file"))
216 {
217  if (componentColumns_.size() != pTraits<Type>::nComponents)
218  {
220  << componentColumns_ << " does not have the expected length of "
222  << exit(FatalError);
223  }
224 
225  read();
226 
228 }
229 
230 
231 template<class Type>
233 :
234  TableBase<Type>(tbl),
235  nHeaderLine_(tbl.nHeaderLine_),
236  refColumn_(tbl.refColumn_),
237  componentColumns_(tbl.componentColumns_),
238  separator_(tbl.separator_),
239  mergeSeparators_(tbl.mergeSeparators_),
240  fName_(tbl.fName_)
241 {}
242 
243 
244 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
245 
246 template<class Type>
248 {}
249 
250 
251 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
252 
253 template<class Type>
255 {
256  return fName_;
257 }
258 
259 
260 template<class Type>
262 {
264  os << token::END_STATEMENT << nl;
265  os << indent << word(this->name() + "Coeffs") << nl;
266  os << indent << token::BEGIN_BLOCK << incrIndent << nl;
267 
268  // Note: for TableBase write the dictionary entries it needs but not
269  // the values themselves
271 
272  writeEntry(os, "nHeaderLine", nHeaderLine_);
273  writeEntry(os, "refColumn", refColumn_);
274  writeEntry(os, "componentColumns", componentColumns_);
275  writeEntry(os, "separator", string(separator_));
276  writeEntry(os, "mergeSeparators", mergeSeparators_);
277  writeEntry(os, "file", fName_);
278 
279  os << decrIndent << indent << token::END_BLOCK << endl;
280 }
281 
282 
283 // ************************************************************************* //
#define readScalar
Definition: doubleScalar.C:38
dictionary dict
CSV(const word &entryName, const dictionary &dict)
Construct from entry name and dictionary.
Definition: CSV.C:204
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
A class for handling file names.
Definition: fileName.H:79
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:226
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:158
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Templated CSV function.
Definition: CSV.H:73
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
const word & name() const
Return the name of the entry.
Definition: Function1.C:56
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
Traits class for primitives.
Definition: pTraits.H:50
bool readBool(Istream &)
Definition: boolIO.C:60
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
virtual void writeData(Ostream &os) const
Write in dictionary format.
Definition: Function1.C:150
Base class for table with bounds handling, interpolation and integration.
Definition: TableBase.H:55
A class for handling words, derived from string.
Definition: word.H:59
virtual void writeData(Ostream &os) const
Write in dictionary format.
Definition: CSV.C:261
const fileOperation & fileHandler()
Get current file handler.
label readLabel(Istream &is)
Definition: label.H:64
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
static const char nl
Definition: Ostream.H:265
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:240
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
virtual ~CSV()
Destructor.
Definition: CSV.C:247
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:331
virtual const fileName & fName() const
Return const access to the file name.
Definition: CSV.C:254
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:233
virtual void writeEntries(Ostream &os) const
Write keywords only in dictionary format. Used for non-inline.
Definition: TableBase.C:412
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:583
IOerror FatalIOError