OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
oofemtxtinputrecord.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 #include "oofemtxtinputrecord.h"
36 #include "intarray.h"
37 #include "floatarray.h"
38 #include "floatmatrix.h"
39 #include "dictionary.h"
40 #include "range.h"
41 #include "scalarfunction.h"
42 
43 #include <cstdlib>
44 #include <cstdio>
45 #include <cstring>
46 #include <cctype>
47 #include <ostream>
48 #include <sstream>
49 
50 namespace oofem {
52 { }
53 
56 {
57  tokenizer.tokenizeLine( this->record );
58  int ntok = tokenizer.giveNumberOfTokens();
59  readFlag.resize(ntok);
60  for ( int i = 0; i < ntok; i++ ) {
61  readFlag [ i ] = src.readFlag [ i ];
62  }
63 }
64 
65 OOFEMTXTInputRecord :: OOFEMTXTInputRecord(int linenumber, std :: string source) : InputRecord(), tokenizer(),
66  record(std :: move(source)), lineNumber(linenumber)
67 {
68  tokenizer.tokenizeLine( this->record );
69  int ntok = tokenizer.giveNumberOfTokens();
70  readFlag.resize(ntok);
71  for ( int i = 0; i < ntok; i++ ) {
72  readFlag [ i ] = false;
73  }
74 }
75 
78 {
79  this->record = src.record;
80  tokenizer.tokenizeLine( this->record );
81  int ntok = tokenizer.giveNumberOfTokens();
82  readFlag.resize(ntok);
83  for ( int i = 0; i < ntok; i++ ) {
84  readFlag [ i ] = src.readFlag [ i ];
85  }
86 
87  return * this;
88 }
89 
90 void
92 {
93  this->record = std :: move(newRec);
94  tokenizer.tokenizeLine( this->record );
95  int ntok = tokenizer.giveNumberOfTokens();
96  readFlag.resize(ntok);
97  for ( int i = 0; i < ntok; i++ ) {
98  readFlag [ i ] = false;
99  }
100 }
101 
103 OOFEMTXTInputRecord :: giveRecordKeywordField(std :: string &answer, int &value)
104 {
105  if ( tokenizer.giveNumberOfTokens() > 0 ) {
106  answer = std :: string( tokenizer.giveToken(1) );
107  setReadFlag(1);
108  auto ptr = scanInteger(tokenizer.giveToken(2), value);
109  if ( ptr == NULL || *ptr != 0 ) {
110  return IRRT_BAD_FORMAT;
111  }
112  setReadFlag(2);
113 
114  return IRRT_OK;
115  } else {
116  return IRRT_BAD_FORMAT;
117  }
118 }
119 
122 {
123  if ( tokenizer.giveNumberOfTokens() > 0 ) {
124  answer = std :: string( tokenizer.giveToken(1) );
125  setReadFlag(1);
126 
127  return IRRT_OK;
128  } else {
129  return IRRT_BAD_FORMAT;
130  }
131 }
132 
135 {
136  int indx = this->giveKeywordIndx(id);
137  if ( indx ) {
138  auto ptr = scanInteger(tokenizer.giveToken(indx + 1), answer);
139  if ( ptr == NULL || *ptr != 0 ) {
140  return IRRT_BAD_FORMAT;
141  }
142 
143  setReadFlag(indx);
144  setReadFlag(indx + 1);
145  return IRRT_OK;
146  } else {
147  return IRRT_NOTFOUND;
148  }
149 }
150 
153 {
154  int indx = this->giveKeywordIndx(id);
155  if ( indx ) {
156  auto ptr = scanDouble(tokenizer.giveToken(indx + 1), answer);
157  if ( ptr == NULL || *ptr != 0 ) {
158  return IRRT_BAD_FORMAT;
159  }
160 
161  setReadFlag(indx);
162  setReadFlag(indx + 1);
163  return IRRT_OK;
164  } else {
165  return IRRT_NOTFOUND;
166  }
167 }
168 
171 {
172  int val;
173  int indx = this->giveKeywordIndx(id);
174  if ( indx ) {
175  auto ptr = scanInteger(tokenizer.giveToken(indx + 1), val);
176  if ( ptr == NULL || *ptr != 0 ) {
177  return IRRT_BAD_FORMAT;
178  }
179 
180  setReadFlag(indx);
181  setReadFlag(indx + 1);
182  answer = val != 0;
183  return IRRT_OK;
184  } else {
185  return IRRT_NOTFOUND;
186  }
187 }
188 
191 {
192  int indx = 0;
193  if ( id ) {
194  if ( ( indx = this->giveKeywordIndx(id) ) == 0 ) {
195  return IRRT_NOTFOUND;
196  }
197 
198  setReadFlag(indx);
199  indx++;
200  } else {
201  indx = 1;
202  }
203 
204  const char *_token = tokenizer.giveToken(indx);
205  if ( _token ) {
206  answer = std :: string( tokenizer.giveToken(indx) );
207  setReadFlag(indx);
208  return IRRT_OK;
209  } else {
210  answer = "";
211  return IRRT_NOTFOUND;
212  }
213 }
214 
217 {
218  int value, size;
219  int indx = this->giveKeywordIndx(id);
220  if ( indx ) {
221  setReadFlag(indx);
222  auto ptr = scanInteger(tokenizer.giveToken(++indx), size);
223  if ( ptr == NULL || *ptr != 0) {
224  return IRRT_BAD_FORMAT;
225  }
226 
227  answer.resize(size);
228  setReadFlag(indx);
229 
230  for ( int i = 1; i <= size; i++ ) {
231  ptr = scanInteger(tokenizer.giveToken(indx + i), value);
232  if ( ptr == NULL || *ptr != 0 ) {
233  return IRRT_BAD_FORMAT;
234  }
235 
236  answer.at(i) = value;
237  setReadFlag(indx + i);
238  }
239 
240  return IRRT_OK;
241  } else {
242  return IRRT_NOTFOUND;
243  }
244 }
245 
248 {
249  double value;
250  int size;
251  int indx = this->giveKeywordIndx(id);
252  if ( indx ) {
253  setReadFlag(indx);
254  auto ptr = scanInteger(tokenizer.giveToken(++indx), size);
255  if ( ptr == NULL || *ptr != 0 ) {
256  return IRRT_BAD_FORMAT;
257  }
258 
259  answer.resize(size);
260  setReadFlag(indx);
261 
262  for ( int i = 1; i <= size; i++ ) {
263  auto ptr = scanDouble(tokenizer.giveToken(indx + i), value);
264  if ( ptr == NULL || *ptr != 0 ) {
265  return IRRT_BAD_FORMAT;
266  }
267 
268  answer.at(i) = value;
269  setReadFlag(indx + i);
270  }
271 
272  return IRRT_OK;
273  } else {
274  return IRRT_NOTFOUND;
275  }
276 }
277 
280 {
281  int nrows, ncols;
282  int indx = this->giveKeywordIndx(id);
283  if ( indx ) {
284  setReadFlag(indx);
285 
286  auto ptr = scanInteger(tokenizer.giveToken(++indx), nrows);
287  if ( ptr == NULL || *ptr != 0 ) {
288  return IRRT_BAD_FORMAT;
289  }
290 
291  setReadFlag(indx);
292  ptr = scanInteger(tokenizer.giveToken(++indx), ncols);
293  if ( ptr == NULL || *ptr != 0 ) {
294  return IRRT_BAD_FORMAT;
295  }
296 
297  setReadFlag(indx);
298 
299  if ( readMatrix(tokenizer.giveToken(++indx), nrows, ncols, answer) == 0 ) {
300  return IRRT_BAD_FORMAT;
301  }
302 
303  setReadFlag(indx);
304  return IRRT_OK;
305  } else {
306  return IRRT_NOTFOUND;
307  }
308 }
309 
311 OOFEMTXTInputRecord :: giveField(std :: vector< std :: string > &answer, InputFieldType id)
312 {
313  int size;
314  int indx = this->giveKeywordIndx(id);
315  if ( indx ) {
316  setReadFlag(indx);
317  auto ptr = scanInteger(tokenizer.giveToken(++indx), size);
318  if ( ptr == NULL || *ptr != 0 ) {
319  return IRRT_BAD_FORMAT;
320  }
321  answer.reserve(size);
322  setReadFlag(indx);
323  for ( int i = 1; i <= size; i++ ) {
324  answer.push_back( tokenizer.giveToken(indx + i) );
325  setReadFlag(indx + i);
326  }
327 
328  return IRRT_OK;
329  } else {
330  return IRRT_NOTFOUND;
331  }
332 }
333 
336 {
337  double value;
338  int size;
339  char key;
340  int indx = this->giveKeywordIndx(id);
341  if ( indx ) {
342  setReadFlag(indx);
343  auto ptr = scanInteger(tokenizer.giveToken(++indx), size);
344  if ( ptr == NULL || *ptr != 0 ) {
345  return IRRT_BAD_FORMAT;
346  }
347 
348  setReadFlag(indx);
349 
350  answer.clear();
351  for ( int i = 1; i <= size; i++ ) {
352  key = ( tokenizer.giveToken(++indx) ) [ 0 ];
353  setReadFlag(indx);
354  auto ptr = scanDouble(tokenizer.giveToken(++indx), value);
355  if ( ptr == NULL || *ptr != 0 ) {
356  return IRRT_BAD_FORMAT;
357  }
358 
359  setReadFlag(indx);
360  answer.add(key, value);
361  }
362 
363  return IRRT_OK;
364  } else {
365  return IRRT_NOTFOUND;
366  }
367 }
368 
370 OOFEMTXTInputRecord :: giveField(std :: list< Range > &list, InputFieldType id)
371 {
372  int li, hi;
373  const char *rec;
374  int indx = this->giveKeywordIndx(id);
375  if ( indx ) {
376  setReadFlag(indx);
377  rec = tokenizer.giveToken(++indx);
378  if ( * rec != '{' ) {
379  OOFEM_WARNING("missing left '{'");
380  list.clear();
381  return IRRT_BAD_FORMAT;
382  }
383 
384  setReadFlag(indx);
385  rec++;
386  // read ranges
387  while ( readRange(& rec, li, hi) ) {
388  Range range(li, hi);
389  list.push_back(range);
390  }
391 
392  // skip whitespaces after last range
393  while ( isspace(* rec) ) {
394  rec++;
395  }
396 
397  // test for enclosing bracket
398  if ( * rec != '}' ) {
399  OOFEM_WARNING("missing end '}'");
400  list.clear();
401  return IRRT_BAD_FORMAT;
402  }
403 
404  return IRRT_OK;
405  } else {
406  return IRRT_NOTFOUND;
407  }
408 }
409 
412 {
413  const char *rec;
414  int indx = this->giveKeywordIndx(id);
415 
416  if ( indx ) {
417  setReadFlag(indx);
418  rec = tokenizer.giveToken(++indx);
419  if ( * rec == '@' ) {
420  // reference to function
421  int refVal;
422  auto ptr = scanInteger(rec + 1, refVal);
423  if ( ptr == NULL || *ptr != 0 ) {
424  return IRRT_BAD_FORMAT;
425  }
426  setReadFlag(indx);
427  answer.setReference(refVal);
428  } else if ( * rec == '$' ) {
429  // simple expression
430  std :: string expr;
431 
432  expr = std :: string( tokenizer.giveToken(indx) );
433  setReadFlag(indx);
434  std :: string _v = expr.substr(1, expr.size() - 2);
435 
436  answer.setSimpleExpression(_v); // get rid of enclosing '$'
437  } else {
438  double val;
439  auto ptr = scanDouble(tokenizer.giveToken(indx), val);
440  if ( ptr == NULL || *ptr != 0 ) {
441  return IRRT_BAD_FORMAT;
442  }
443 
444  setReadFlag(indx);
445  answer.setValue(val);
446  }
447 
448  return IRRT_OK;
449  } else {
450  return IRRT_NOTFOUND;
451  }
452 }
453 
454 bool
456 {
457  //returns nonzero if id is present in source
458  int indx = this->giveKeywordIndx(id);
459  if ( indx ) {
460  setReadFlag(indx);
461  }
462 
463  return ( indx > 0 ) ? true : false;
464 }
465 
466 void
468 {
469  printf( "%s", this->record.c_str() );
470 }
471 
472 const char *
473 OOFEMTXTInputRecord :: scanInteger(const char *source, int &value)
474 {
475  //
476  // reads integer value from source, returns pointer to char after this number
477  //
478  char *endptr;
479 
480  if ( source == NULL ) {
481  value = 0;
482  return NULL;
483  }
484 
485  value = strtol(source, & endptr, 10);
486  return endptr;
487 }
488 
489 const char *
490 OOFEMTXTInputRecord :: scanDouble(const char *source, double &value)
491 {
492  //
493  // reads double value from source, returns pointer to char after this number
494  //
495  char *endptr;
496 
497  if ( source == NULL ) {
498  value = 0;
499  return NULL;
500  }
501 
502  value = strtod(source, & endptr);
503  return endptr;
504 }
505 
506 int
508 {
509  int ntokens = tokenizer.giveNumberOfTokens();
510  for ( int i = 1; i <= ntokens; i++ ) {
511  if ( strcmp( kwd, tokenizer.giveToken(i) ) == 0 ) {
512  return i;
513  }
514  }
515 
516  return 0;
517 }
518 
519 void
521 {
522  if ( !wrn ) {
523  return;
524  }
525 
526  std :: ostringstream buff;
527  bool pf = true, wf = false;
528  int ntokens = tokenizer.giveNumberOfTokens();
529  for ( int i = 0; i < ntokens; i++ ) {
530  //fprintf (stderr, "[%s] ", tokenizer.giveToken(i+1));
531  if ( !readFlag [ i ] ) {
532  if ( pf ) {
533  buff << "Unread token(s) detected in the following record\n\"";
534  for ( int j = 0; j < 40; j++ ) {
535  if ( this->record [ j ] == '\n' || this->record [ j ] == '\0' ) {
536  break;
537  } else {
538  buff << this->record [ j ];
539  }
540  }
541  if ( this->record.size() > 41 ) {
542  buff << "...";
543  }
544  buff << "\":\n";
545 
546  pf = false;
547  wf = true;
548  }
549 
550  buff << "[" << tokenizer.giveToken(i + 1) << "]";
551  }
552  }
553 
554  if ( wf ) {
555  OOFEM_WARNING( buff.str().c_str() );
556  }
557 }
558 
559 int
560 OOFEMTXTInputRecord :: readRange(const char **helpSource, int &li, int &hi)
561 {
562  char *endptr;
563  // skip whitespaces
564  while ( isspace(* * helpSource) ) {
565  ( * helpSource )++;
566  }
567 
568  // test if character is digit
569  if ( isdigit(* * helpSource) ) {
570  // digit character - read one value range
571  li = hi = strtol(* helpSource, & endptr, 10);
572  * helpSource = endptr;
573  return 1;
574  } else if ( * * helpSource == '(' ) {
575  // range left parenthesis found
576  ( * helpSource )++;
577  // read lower index
578  li = strtol(* helpSource, & endptr, 10);
579  * helpSource = endptr;
580  // test whitespaces
581  if ( * * helpSource != ' ' && * * helpSource != '\t' ) {
582  OOFEM_WARNING("unexpected token while reading range value");
583  return 0;
584  }
585 
586  // read end index
587  hi = strtol(* helpSource, & endptr, 10);
588  * helpSource = endptr;
589  // skip whitespaces
590  while ( isspace(* * helpSource) ) {
591  ( * helpSource )++;
592  }
593 
594  // test for enclosing bracket
595  if ( * * helpSource == ')' ) {
596  ( * helpSource )++;
597  return 1;
598  } else {
599  OOFEM_WARNING("end ')' missing while parsing range value");
600  return 0;
601  }
602  }
603 
604  return 0;
605 }
606 
607 int
608 OOFEMTXTInputRecord :: readMatrix(const char *helpSource, int r, int c, FloatMatrix &ans)
609 {
610  const char *endptr = helpSource;
611 
612  if ( helpSource == NULL ) {
613  ans.clear();
614  return 0;
615  }
616 
617  ans.resize(r, c);
618  // skip whitespaces
619  while ( isspace(* endptr) ) {
620  ( endptr )++;
621  }
622 
623  if ( * endptr == '{' ) {
624  // range left parenthesis found
625  ( endptr )++;
626  // read row by row separated by semicolon
627  for ( int i = 1; i <= r; i++ ) {
628  for ( int j = 1; j <= c; j++ ) {
629  endptr = scanDouble( endptr, ans.at(i, j) );
630  }
631 
632  if ( i < r ) {
633  // skip whitespaces
634  while ( isspace(* endptr) ) {
635  ( endptr )++;
636  }
637 
638  // test for row terminating semicolon
639  if ( * endptr == ';' ) {
640  ( endptr )++;
641  } else {
642  OOFEM_WARNING("missing row terminating semicolon");
643  return 0;
644  }
645  }
646  }
647 
648  // skip whitespaces
649  while ( isspace(* endptr) ) {
650  ( endptr )++;
651  }
652 
653  // test for enclosing bracket
654  if ( * endptr == '}' ) {
655  return 1;
656  } else {
657  OOFEM_WARNING("end '}' missing while parsing matrix value");
658  return 0;
659  }
660  } else {
661  return 0;
662  }
663 
664 }
665 
666 
667 void
668 OOFEMTXTInputRecord :: report_error(const char *_class, const char *proc, InputFieldType id,
669  IRResultType result, const char *file, int line)
670 {
672  "Input error on line %d: \"%s\", field keyword \"%s\"\nIn function %s::%s\nRecord:\"%s\"",
673  lineNumber, strerror(result), id, _class, proc, this->giveRecordAsString().c_str());
674  OOFEM_EXIT(1);
675 }
676 } // end namespace oofem
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
const char * strerror(IRResultType)
Returns error string corresponding to given value of IRResultType type.
Definition: inputrecord.C:49
virtual std::string giveRecordAsString() const
Returns record string.
void finish(bool wrn=true)
Terminates the current record session and if the flag is true, warning is printed for unscanned token...
const char * InputFieldType
Identifier of fields in input records.
Definition: inputrecord.h:52
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
void setValue(double val)
Sets receiver to be a constant scalar function defined by given value.
const char * scanInteger(const char *source, int &value)
OOFEMTXTInputRecord()
Constructor. Creates an empty input record.
virtual void report_error(const char *_class, const char *proc, InputFieldType id, IRResultType result, const char *file, int line)
Prints the error message.
void writeELogMsg(logLevelType level, const char *_func, const char *_file, int _line, const char *format,...)
Writes extended log message with file and line info.
Definition: logger.C:265
void setReference(int val)
Sets receiver to be a scalar function defined using external function.
std::vector< bool > readFlag
const char * giveToken(int i)
Returns pointer to i-th token.
Definition: tokenizer.C:146
Tokenizer tokenizer
Tokenizer is used to parse records.
Class Range is an abstraction for interval of integer numbers.
Definition: range.h:50
void setSimpleExpression(std::string &val)
Sets receiver to be a scalar funtion defined by given simple expression.
void tokenizeLine(const std::string &line)
Tokenizes given record (string).
Definition: tokenizer.C:110
std::string record
Record representation.
void clear()
Clears the receiver.
Definition: dictionary.C:52
double at(int i, int j) const
Coefficient access function.
Definition: floatmatrix.h:176
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
Logger oofem_logger(Logger::LOG_LEVEL_INFO)
Definition: logger.h:115
OOFEMTXTInputRecord & operator=(const OOFEMTXTInputRecord &)
Assignment operator.
Pair * add(int aKey, double value)
Adds a new Pair with given keyword and value into receiver.
Definition: dictionary.C:81
This class implements a linked list whose entries are Pairs (see below).
Definition: dictionary.h:58
Class representing vector of real numbers.
Definition: floatarray.h:82
Implementation of matrix containing floating point numbers.
Definition: floatmatrix.h:94
virtual bool hasField(InputFieldType id)
Returns true if record contains field identified by idString keyword.
Class representing the Input Record for OOFEM txt input file format.
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
Implementation of Scalar function.
#define OOFEM_EXIT(code)
Cause oofem program termination by calling exit.
Definition: error.h:50
int giveKeywordIndx(const char *kwd)
void resize(int rows, int cols)
Checks size of receiver towards requested bounds.
Definition: floatmatrix.C:1358
Class representing the general Input Record.
Definition: inputrecord.h:101
virtual IRResultType giveRecordKeywordField(std::string &answer, int &value)
Reads the record id field (type of record) and its corresponding number.
virtual IRResultType giveField(int &answer, InputFieldType id)
Reads the integer field value.
int readMatrix(const char *helpSource, int r, int c, FloatMatrix &ans)
Reads single matrix record from input record represented by *helpSource string.
int readRange(const char **helpSource, int &li, int &hi)
Reads single range record from input record represented by *helpSource string.
the oofem namespace is to define a context or scope in which all oofem names are defined.
void clear()
Sets size of receiver to be an empty matrix. It will have zero rows and zero columns size...
Definition: floatmatrix.h:516
void setRecordString(std::string newStr)
Sets the record string.
virtual void printYourself()
Print input record.
const char * scanDouble(const char *source, double &value)
#define OOFEM_WARNING(...)
Definition: error.h:62
int giveNumberOfTokens()
returns the number of tokens.
Definition: tokenizer.C:140
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:30 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011