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-2018 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 //#include "IFstream.H"
29 
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 
32 template<>
34 (
35  const List<string>& split
36 )
37 {
38  if (componentColumns_[0] >= split.size())
39  {
41  << "No column " << componentColumns_[0] << " in "
42  << split << endl
43  << exit(FatalError);
44  }
45 
46  return readLabel(IStringStream(split[componentColumns_[0]])());
47 }
48 
49 
50 template<>
52 (
53  const List<string>& split
54 )
55 {
56  if (componentColumns_[0] >= split.size())
57  {
59  << "No column " << componentColumns_[0] << " in "
60  << split << endl
61  << exit(FatalError);
62  }
63 
64  return readScalar(IStringStream(split[componentColumns_[0]])());
65 }
66 
67 
68 template<class Type>
69 Type Foam::Function1Types::CSV<Type>::readValue(const List<string>& split)
70 {
71  Type result;
72 
73  for (label i = 0; i < pTraits<Type>::nComponents; i++)
74  {
75  if (componentColumns_[i] >= split.size())
76  {
78  << "No column " << componentColumns_[i] << " in "
79  << split << endl
80  << exit(FatalError);
81  }
82 
83  result[i] =
84  readScalar(IStringStream(split[componentColumns_[i]])());
85  }
86 
87  return result;
88 }
89 
90 
91 template<class Type>
93 {
94  fileName expandedFile(fName_);
95  // IFstream is(expandedFile.expand());
96  autoPtr<ISstream> isPtr(fileHandler().NewIFstream(expandedFile.expand()));
97  ISstream& is = isPtr();
98 
99  if (!is.good())
100  {
102  << "Cannot open CSV file for reading."
103  << exit(FatalIOError);
104  }
105 
106  DynamicList<Tuple2<scalar, Type>> values;
107 
108  // skip header
109  for (label i = 0; i < nHeaderLine_; i++)
110  {
111  string line;
112  is.getLine(line);
113  }
114 
115  label nEntries = max(componentColumns_);
116 
117  // read data
118  while (is.good())
119  {
120  string line;
121  is.getLine(line);
122 
123 
124  label n = 0;
125  std::size_t pos = 0;
126  DynamicList<string> split;
127 
128  if (mergeSeparators_)
129  {
130  std::size_t nPos = 0;
131 
132  while ((pos != std::string::npos) && (n <= nEntries))
133  {
134  bool found = false;
135  while (!found)
136  {
137  nPos = line.find(separator_, pos);
138 
139  if ((nPos != std::string::npos) && (nPos - pos == 0))
140  {
141  pos = nPos + 1;
142  }
143  else
144  {
145  found = true;
146  }
147  }
148 
149  nPos = line.find(separator_, pos);
150 
151  if (nPos == std::string::npos)
152  {
153  split.append(line.substr(pos));
154  pos = nPos;
155  n++;
156  }
157  else
158  {
159  split.append(line.substr(pos, nPos - pos));
160  pos = nPos + 1;
161  n++;
162  }
163  }
164  }
165  else
166  {
167  while ((pos != std::string::npos) && (n <= nEntries))
168  {
169  std::size_t nPos = line.find(separator_, pos);
170 
171  if (nPos == std::string::npos)
172  {
173  split.append(line.substr(pos));
174  pos = nPos;
175  n++;
176  }
177  else
178  {
179  split.append(line.substr(pos, nPos - pos));
180  pos = nPos + 1;
181  n++;
182  }
183  }
184  }
185 
186 
187  if (split.size() <= 1)
188  {
189  break;
190  }
191 
192  scalar x = readScalar(IStringStream(split[refColumn_])());
193  Type value = readValue(split);
194 
195  values.append(Tuple2<scalar,Type>(x, value));
196  }
197 
198  this->table_.transfer(values);
199 }
200 
201 
202 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
203 
204 template<class Type>
206 (
207  const word& entryName,
208  const dictionary& dict
209 )
210 :
211  TableBase<Type>(entryName, dict),
212  nHeaderLine_(readLabel(dict.lookup("nHeaderLine"))),
213  refColumn_(readLabel(dict.lookup("refColumn"))),
214  componentColumns_(dict.lookup("componentColumns")),
215  separator_(dict.lookupOrDefault<string>("separator", string(","))[0]),
216  mergeSeparators_(readBool(dict.lookup("mergeSeparators"))),
217  fName_(dict.lookup("file"))
218 {
219  if (componentColumns_.size() != pTraits<Type>::nComponents)
220  {
222  << componentColumns_ << " does not have the expected length of "
224  << exit(FatalError);
225  }
226 
227  read();
228 
230 }
231 
232 
233 template<class Type>
235 :
236  TableBase<Type>(tbl),
237  nHeaderLine_(tbl.nHeaderLine_),
238  refColumn_(tbl.refColumn_),
239  componentColumns_(tbl.componentColumns_),
240  separator_(tbl.separator_),
241  mergeSeparators_(tbl.mergeSeparators_),
242  fName_(tbl.fName_)
243 {}
244 
245 
246 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
247 
248 template<class Type>
250 {}
251 
252 
253 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
254 
255 template<class Type>
257 {
258  return fName_;
259 }
260 
261 
262 template<class Type>
264 {
266  os << token::END_STATEMENT << nl;
267  os << indent << word(this->name() + "Coeffs") << nl;
268  os << indent << token::BEGIN_BLOCK << incrIndent << nl;
269 
270  // Note: for TableBase write the dictionary entries it needs but not
271  // the values themselves
273 
274  os.writeKeyword("nHeaderLine") << nHeaderLine_ << token::END_STATEMENT
275  << nl;
276 
277  os.writeKeyword("refColumn") << refColumn_ << token::END_STATEMENT << nl;
278 
279  componentColumns_.writeEntry("componentColumns", os);
280 
281  os.writeKeyword("separator") << string(separator_)
282  << token::END_STATEMENT << nl;
283  os.writeKeyword("mergeSeparators") << mergeSeparators_
284  << token::END_STATEMENT << nl;
285  os.writeKeyword("file") << fName_ << token::END_STATEMENT << nl;
286  os << decrIndent << indent << token::END_BLOCK << endl;
287 }
288 
289 
290 // ************************************************************************* //
#define readScalar
Definition: doubleScalar.C:38
dictionary dict
CSV(const word &entryName, const dictionary &dict)
Construct from entry name and dictionary.
Definition: CSV.C:206
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:69
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:137
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:146
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:263
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
Ostream & writeKeyword(const keyType &)
Write the keyword followed by an appropriate indentation.
Definition: Ostream.C:54
virtual ~CSV()
Destructor.
Definition: CSV.C:249
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:256
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:233
A class for handling character strings derived from std::string.
Definition: string.H:74
virtual void writeEntries(Ostream &os) const
Write keywords only in dictionary format. Used for non-inline.
Definition: TableBase.C:412
void writeEntry(Ostream &) const
Write the UList as a dictionary entry.
Definition: UListIO.C:35
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:576
IOerror FatalIOError