OOFEM 3.0
Loading...
Searching...
No Matches
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 - 2025 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#include "datareader.h"
43
44#include <cstdlib>
45#include <cstdio>
46#include <cstring>
47#include <cctype>
48#include <ostream>
49#include <sstream>
50
51
52namespace oofem {
53
54OOFEMTXTInputRecord :: OOFEMTXTInputRecord() : tokenizer(), record()
55{ }
56
57OOFEMTXTInputRecord :: OOFEMTXTInputRecord(const OOFEMTXTInputRecord &src) : tokenizer(),
59{
60 tokenizer.tokenizeLine( this->record );
61 int ntok = tokenizer.giveNumberOfTokens();
62 readFlag.resize(ntok);
63 for ( int i = 0; i < ntok; i++ ) {
64 readFlag [ i ] = src.readFlag [ i ];
65 }
66}
67
68OOFEMTXTInputRecord :: OOFEMTXTInputRecord(int linenumber, std :: string source) : tokenizer(),
69 record(std :: move(source)), lineNumber(linenumber)
70{
71 tokenizer.tokenizeLine( this->record );
72 int ntok = tokenizer.giveNumberOfTokens();
73 readFlag.resize(ntok);
74 for ( int i = 0; i < ntok; i++ ) {
75 readFlag [ i ] = false;
76 }
77}
78
80OOFEMTXTInputRecord :: operator = ( const OOFEMTXTInputRecord & src )
81{
82 this->record = src.record;
84 tokenizer.tokenizeLine( this->record );
85 int ntok = tokenizer.giveNumberOfTokens();
86 readFlag.resize(ntok);
87 for ( int i = 0; i < ntok; i++ ) {
88 readFlag [ i ] = src.readFlag [ i ];
89 }
90
91 return * this;
92}
93
94
95std :: string
97 return std::string(giveReader()?giveReader()->giveReferenceName():"<?reader_NULL?>")+":"+std::to_string(giveLineNumber());
98}
99
100int
101OOFEMTXTInputRecord :: giveGroupCount(InputFieldType id, const std::string& name, bool optional){
102 int size=0;
103 if(optional) giveOptionalField(size,id);
104 else giveField(size,id);
105 return size;
106}
107
108bool
109OOFEMTXTInputRecord :: hasChild(InputFieldType id, const std::string& name, bool optional){
110 if(id[0]=='\0') return true;
111 int count=this->giveGroupCount(id,name,optional);
112 if(count>1) OOFEM_ERROR("Number of '%s' children (%s) must be 0 or 1 (not %d)",name.c_str(),id,count);
113 return count>0;
114}
115
116void
117OOFEMTXTInputRecord :: setRecordString(std :: string newRec)
118{
119 this->record = std :: move(newRec);
120 tokenizer.tokenizeLine( this->record );
121 int ntok = tokenizer.giveNumberOfTokens();
122 readFlag.resize(ntok);
123 for ( int i = 0; i < ntok; i++ ) {
124 readFlag [ i ] = false;
125 }
126}
127
128void
129OOFEMTXTInputRecord :: giveRecordKeywordField(std :: string &answer, int &value)
130{
131 if ( tokenizer.giveNumberOfTokens() > 0 ) {
132 answer = std :: string( tokenizer.giveToken(1) );
133 setReadFlag(1);
134 auto ptr = scanInteger(tokenizer.giveToken(2), value);
135 if ( ptr == nullptr || *ptr != 0 ) {
136 throw BadFormatInputException(*this, "RecordID", lineNumber);
137 }
138 setReadFlag(2);
139 } else {
140 throw BadFormatInputException(*this, "RecordID", lineNumber);
141 }
142}
143
144void
145OOFEMTXTInputRecord :: giveRecordKeywordField(std :: string &answer)
146{
147 if ( tokenizer.giveNumberOfTokens() > 0 ) {
148 answer = std :: string( tokenizer.giveToken(1) );
149 setReadFlag(1);
150 } else {
151 throw BadFormatInputException(*this, "RecordID", lineNumber);
152 }
153}
154
155void
156OOFEMTXTInputRecord :: giveField(int &answer, InputFieldType id)
157{
158 traceField(id,"int");
159 int indx = this->giveKeywordIndx(id);
160 if ( indx ) {
161 auto ptr = scanInteger(tokenizer.giveToken(indx + 1), answer);
162 if ( ptr == nullptr || *ptr != 0 ) {
163 throw BadFormatInputException(*this, id, lineNumber);
164 }
165
166 setReadFlag(indx);
167 setReadFlag(indx + 1);
168 } else {
170 }
171}
172
173void
174OOFEMTXTInputRecord :: giveField(double &answer, InputFieldType id)
175{
176 traceField(id,"double");
177 int indx = this->giveKeywordIndx(id);
178 if ( indx ) {
179 auto ptr = scanDouble(tokenizer.giveToken(indx + 1), answer);
180 if ( ptr == nullptr || *ptr != 0 ) {
181 throw BadFormatInputException(*this, id, lineNumber);
182 }
183
184 setReadFlag(indx);
185 setReadFlag(indx + 1);
186 } else {
188 }
189}
190
191void
192OOFEMTXTInputRecord :: giveField(bool &answer, InputFieldType id)
193{
194 traceField(id,"bool");
195 int indx = this->giveKeywordIndx(id);
196 if ( indx ) {
197 int val;
198 auto ptr = scanInteger(tokenizer.giveToken(indx + 1), val);
199 if ( ptr == nullptr || *ptr != 0 ) {
200 throw BadFormatInputException(*this, id, lineNumber);
201 }
202
203 setReadFlag(indx);
204 setReadFlag(indx + 1);
205 answer = val != 0;
206 } else {
208 }
209}
210
211void
212OOFEMTXTInputRecord :: giveField(std :: string &answer, InputFieldType id)
213{
214 traceField(id,"std::string");
215 int indx = 0;
216 if ( id ) {
217 if ( ( indx = this->giveKeywordIndx(id) ) == 0 ) {
219 }
220
221 setReadFlag(indx);
222 indx++;
223 } else {
224 indx = 1;
225 }
226
227 const char *_token = tokenizer.giveToken(indx);
228 if ( _token ) {
229 answer = std :: string( tokenizer.giveToken(indx) );
230 setReadFlag(indx);
231 } else {
232 answer = "";
234 }
235}
236
237void
238OOFEMTXTInputRecord :: giveField(IntArray &answer, InputFieldType id)
239{
240 traceField(id,"IntArray");
241 int indx = this->giveKeywordIndx(id);
242 if ( indx ) {
243 int size;
244 setReadFlag(indx);
245 auto ptr = scanInteger(tokenizer.giveToken(++indx), size);
246 if ( ptr == nullptr || *ptr != 0) {
247 throw BadFormatInputException(*this, id, lineNumber);
248 }
249
250 answer.resize(size);
251 setReadFlag(indx);
252
253 for ( int i = 1; i <= size; i++ ) {
254 int value;
255 ptr = scanInteger(tokenizer.giveToken(indx + i), value);
256 if ( ptr == nullptr || *ptr != 0 ) {
257 throw BadFormatInputException(*this, id, lineNumber);
258 }
259
260 answer.at(i) = value;
261 setReadFlag(indx + i);
262 }
263
264 } else {
266 }
267}
268
269void
270OOFEMTXTInputRecord :: giveField(FloatArray &answer, InputFieldType id)
271{
272 traceField(id,"FloatArray");
273 int indx = this->giveKeywordIndx(id);
274 if ( indx ) {
275 int size;
276 setReadFlag(indx);
277 auto ptr = scanInteger(tokenizer.giveToken(++indx), size);
278 if ( ptr == nullptr || *ptr != 0 ) {
279 throw BadFormatInputException(*this, id, lineNumber);
280 }
281
282 answer.resize(size);
283 setReadFlag(indx);
284
285 for ( int i = 1; i <= size; i++ ) {
286 double value;
287 auto ptr = scanDouble(tokenizer.giveToken(indx + i), value);
288 if ( ptr == nullptr || *ptr != 0 ) {
289 throw BadFormatInputException(*this, id, lineNumber);
290 }
291
292 answer.at(i) = value;
293 setReadFlag(indx + i);
294 }
295
296 } else {
298 }
299}
300
301void
302OOFEMTXTInputRecord :: giveField(FloatMatrix &answer, InputFieldType id)
303{
304 traceField(id,"FloatMatrix");
305 int indx = this->giveKeywordIndx(id);
306 if ( indx ) {
307 int nrows, ncols;
308 setReadFlag(indx);
309
310 auto ptr = scanInteger(tokenizer.giveToken(++indx), nrows);
311 if ( ptr == nullptr || *ptr != 0 ) {
312 throw BadFormatInputException(*this, id, lineNumber);
313 }
314
315 setReadFlag(indx);
316 ptr = scanInteger(tokenizer.giveToken(++indx), ncols);
317 if ( ptr == nullptr || *ptr != 0 ) {
318 throw BadFormatInputException(*this, id, lineNumber);
319 }
320
321 setReadFlag(indx);
322
323 if ( readMatrix(tokenizer.giveToken(++indx), nrows, ncols, answer) == 0 ) {
324 throw BadFormatInputException(*this, id, lineNumber);
325 }
326
327 setReadFlag(indx);
328 } else {
330 }
331}
332
333void
334OOFEMTXTInputRecord :: giveField(std :: vector< std :: string > &answer, InputFieldType id)
335{
336 traceField(id,"std::vector<std::string>");
337 int indx = this->giveKeywordIndx(id);
338 if ( indx ) {
339 int size;
340 setReadFlag(indx);
341 auto ptr = scanInteger(tokenizer.giveToken(++indx), size);
342 if ( ptr == nullptr || *ptr != 0 ) {
343 throw BadFormatInputException(*this, id, lineNumber);
344 }
345 answer.reserve(size);
346 setReadFlag(indx);
347 for ( int i = 1; i <= size; i++ ) {
348 answer.push_back( tokenizer.giveToken(indx + i) );
349 setReadFlag(indx + i);
350 }
351
352 } else {
354 }
355}
356
357void
358OOFEMTXTInputRecord :: giveField(Dictionary &answer, InputFieldType id)
359{
360 traceField(id,"Dictionary");
361 int indx = this->giveKeywordIndx(id);
362 if ( indx ) {
363 setReadFlag(indx);
364 int size;
365 auto ptr = scanInteger(tokenizer.giveToken(++indx), size);
366 if ( ptr == nullptr || *ptr != 0 ) {
367 throw BadFormatInputException(*this, id, lineNumber);
368 }
369
370 setReadFlag(indx);
371
372 answer.clear();
373 for ( int i = 1; i <= size; i++ ) {
374 int key = 0;
375 const char * token = tokenizer.giveToken(++indx);
376 auto ptr1 = scanInteger( token, key );
377 if ( ptr1 == nullptr || *ptr1 != 0 ) {
378 key = token [ 0 ];
379 // throw BadFormatInputException(*this, id, lineNumber);
380 }
381 double value;
382 setReadFlag(indx);
383 auto ptr = scanDouble(tokenizer.giveToken(++indx), value);
384 if ( ptr == nullptr || *ptr != 0 ) {
385 throw BadFormatInputException(*this, id, lineNumber);
386 }
387
388 setReadFlag(indx);
389 answer.add(key, value);
390 }
391 } else {
393 }
394}
395
396void
397OOFEMTXTInputRecord :: giveField(std :: list< Range > &list, InputFieldType id)
398{
399 traceField(id,"std::list<Range>");
400 int indx = this->giveKeywordIndx(id);
401 if ( indx ) {
402 int li, hi;
403 setReadFlag(indx);
404 const char *rec = tokenizer.giveToken(++indx);
405 if ( * rec != '{' ) {
406 OOFEM_WARNING("missing left '{'");
407 list.clear();
408 throw BadFormatInputException(*this, id, lineNumber);
409 }
410
411 setReadFlag(indx);
412 rec++;
413 // read ranges
414 while ( readRange(& rec, li, hi) ) {
415 Range range(li, hi);
416 list.push_back(range);
417 }
418
419 // skip whitespaces after last range
420 while ( isspace(* rec) ) {
421 rec++;
422 }
423
424 // test for enclosing bracket
425 if ( * rec != '}' ) {
426 OOFEM_WARNING("missing end '}'");
427 list.clear();
428 throw BadFormatInputException(*this, id, lineNumber);
429 }
430 } else {
432 }
433}
434
435void
436OOFEMTXTInputRecord :: giveField(ScalarFunction &answer, InputFieldType id)
437{
438 traceField(id,"ScalarFunction");
439 const char *rec;
440 int indx = this->giveKeywordIndx(id);
441
442 if ( indx ) {
443 setReadFlag(indx);
444 rec = tokenizer.giveToken(++indx);
445 if ( * rec == '@' ) {
446 // reference to function
447 int refVal;
448 auto ptr = scanInteger(rec + 1, refVal);
449 if ( ptr == nullptr || *ptr != 0 ) {
450 throw BadFormatInputException(*this, id, lineNumber);
451 }
452 setReadFlag(indx);
453 answer.setReference(refVal);
454 } else if ( * rec == '$' ) {
455 // simple expression
456 std :: string expr;
457
458 expr = std :: string( tokenizer.giveToken(indx) );
459 setReadFlag(indx);
460 std :: string _v = expr.substr(1, expr.size() - 2);
461
462 answer.setSimpleExpression(_v); // get rid of enclosing '$'
463 } else {
464 double val;
465 auto ptr = scanDouble(tokenizer.giveToken(indx), val);
466 if ( ptr == nullptr || *ptr != 0 ) {
467 throw BadFormatInputException(*this, id, lineNumber);
468 }
469
470 setReadFlag(indx);
471 answer.setValue(val);
472 }
473 } else {
475 }
476}
477
478bool
479OOFEMTXTInputRecord :: hasField(InputFieldType id)
480{
481 traceField(id,"flag");
482 //returns nonzero if id is present in source
483 int indx = this->giveKeywordIndx(id);
484 if ( indx ) {
485 setReadFlag(indx);
486 }
487
488 return ( indx > 0 ) ? true : false;
489}
490
491void
492OOFEMTXTInputRecord :: printYourself()
493{
494 printf( "%s", this->record.c_str() );
495}
496
497const char *
498OOFEMTXTInputRecord :: scanInteger(const char *source, int &value)
499{
500 //
501 // reads integer value from source, returns pointer to char after this number
502 //
503 char *endptr;
504
505 if ( source == nullptr ) {
506 value = 0;
507 return nullptr;
508 }
509
510 value = strtol(source, & endptr, 10);
511 return endptr;
512}
513
514const char *
515OOFEMTXTInputRecord :: scanDouble(const char *source, double &value)
516{
517 //
518 // reads double value from source, returns pointer to char after this number
519 //
520 char *endptr;
521
522 if ( source == nullptr ) {
523 value = 0;
524 return nullptr;
525 }
526
527 value = strtod(source, & endptr);
528 return endptr;
529}
530
531int
532OOFEMTXTInputRecord :: giveKeywordIndx(const char *kwd)
533{
534 int ntokens = tokenizer.giveNumberOfTokens();
535 for ( int i = 1; i <= ntokens; i++ ) {
536 if ( strcmp( kwd, tokenizer.giveToken(i) ) == 0 ) {
537 return i;
538 }
539 }
540
541 return 0;
542}
543
544void
545OOFEMTXTInputRecord :: finish(bool wrn)
546{
547 if ( !wrn ) {
548 return;
549 }
550
551 std :: ostringstream buff;
552 bool pf = true, wf = false;
553 int ntokens = tokenizer.giveNumberOfTokens();
554 for ( int i = 0; i < ntokens; i++ ) {
555 //fprintf (stderr, "[%s] ", tokenizer.giveToken(i+1));
556 if ( !readFlag [ i ] ) {
557 if ( pf ) {
558 buff << "Unread token(s) detected in the following record\n\"";
559 for ( int j = 0; j < 40; j++ ) {
560 if ( this->record [ j ] == '\n' || this->record [ j ] == '\0' ) {
561 break;
562 } else {
563 buff << this->record [ j ];
564 }
565 }
566 if ( this->record.size() > 41 ) {
567 buff << "...";
568 }
569 buff << "\":\n";
570
571 pf = false;
572 wf = true;
573 }
574
575 buff << "[" << tokenizer.giveToken(i + 1) << "]";
576 }
577 }
578
579 if ( wf ) {
580 OOFEM_WARNING("%s", buff.str().c_str() );
581 }
582}
583
584int
585OOFEMTXTInputRecord :: readRange(const char **helpSource, int &li, int &hi)
586{
587 char *endptr;
588 // skip whitespaces
589 while ( isspace(* * helpSource) ) {
590 ( * helpSource )++;
591 }
592
593 // test if character is digit
594 if ( isdigit(* * helpSource) ) {
595 // digit character - read one value range
596 li = hi = strtol(* helpSource, & endptr, 10);
597 * helpSource = endptr;
598 return 1;
599 } else if ( * * helpSource == '(' ) {
600 // range left parenthesis found
601 ( * helpSource )++;
602 // read lower index
603 li = strtol(* helpSource, & endptr, 10);
604 * helpSource = endptr;
605 // test whitespaces
606 if ( * * helpSource != ' ' && * * helpSource != '\t' ) {
607 OOFEM_WARNING("unexpected token while reading range value");
608 return 0;
609 }
610
611 // read end index
612 hi = strtol(* helpSource, & endptr, 10);
613 * helpSource = endptr;
614 // skip whitespaces
615 while ( isspace(* * helpSource) ) {
616 ( * helpSource )++;
617 }
618
619 // test for enclosing bracket
620 if ( * * helpSource == ')' ) {
621 ( * helpSource )++;
622 return 1;
623 } else {
624 OOFEM_WARNING("end ')' missing while parsing range value");
625 return 0;
626 }
627 }
628
629 return 0;
630}
631
632int
633OOFEMTXTInputRecord :: readMatrix(const char *helpSource, int r, int c, FloatMatrix &ans)
634{
635 const char *endptr = helpSource;
636
637 if ( helpSource == NULL ) {
638 ans.clear();
639 return 0;
640 }
641
642 ans.resize(r, c);
643 // skip whitespaces
644 while ( isspace(* endptr) ) {
645 ( endptr )++;
646 }
647
648 if ( * endptr == '{' ) {
649 // range left parenthesis found
650 ( endptr )++;
651 // read row by row separated by semicolon
652 for ( int i = 1; i <= r; i++ ) {
653 for ( int j = 1; j <= c; j++ ) {
654 endptr = scanDouble( endptr, ans.at(i, j) );
655 }
656
657 if ( i < r ) {
658 // skip whitespaces
659 while ( isspace(* endptr) ) {
660 ( endptr )++;
661 }
662
663 // test for row terminating semicolon
664 if ( * endptr == ';' ) {
665 ( endptr )++;
666 } else {
667 OOFEM_WARNING("missing row terminating semicolon");
668 return 0;
669 }
670 }
671 }
672
673 // skip whitespaces
674 while ( isspace(* endptr) ) {
675 ( endptr )++;
676 }
677
678 // test for enclosing bracket
679 if ( * endptr == '}' ) {
680 return 1;
681 } else {
682 OOFEM_WARNING("end '}' missing while parsing matrix value");
683 return 0;
684 }
685 } else {
686 return 0;
687 }
688}
689
690#ifdef _USE_TRACE_FIELDS
691 void OOFEMTXTInputRecord::traceField(InputFieldType id, const char* type) {
692 if(!InputRecord::TraceFields::active) return;
693 std::string tag;
694 /* synthetic tags for records which have no leading tag (only data) */
695 if(inputRecordType==DataReader::IR_outManRec) tag="~OutputManager~";
696 else if(inputRecordType==DataReader::IR_domainCompRec) tag="~DomainCompRec~";
697 else if(inputRecordType==DataReader::IR_mstepRec) tag="~MetaStep~";
698 else if(inputRecordType==DataReader::IR_unspecified) tag="?UNSPECIFIED?";
699 else this->giveRecordKeywordField(tag);
700 InputRecord::TraceFields::write(tag+";"+id+";"+type);
701 }
702#endif
703
704} // end namespace oofem
void clear()
Clears the receiver.
Definition dictionary.C:52
Pair * add(int aKey, double value)
Definition dictionary.C:79
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
double at(std::size_t i, std::size_t j) const
void giveOptionalField(T &answer, InputFieldType id)
void traceField(InputFieldType id, const char *type) const
DataReader * giveReader() const
std::shared_ptr< InputRecord > ptr()
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
std::string giveLocation() const override
OOFEMTXTInputRecord()
Constructor. Creates an empty input record.
const char * scanInteger(const char *source, int &value)
int readRange(const char **helpSource, int &li, int &hi)
std ::vector< bool > readFlag
int giveKeywordIndx(const char *kwd)
DataReader::InputRecordType inputRecordType
int giveGroupCount(InputFieldType id, const std::string &name, bool optional) override
const char * scanDouble(const char *source, double &value)
void giveField(int &answer, InputFieldType id) override
Reads the integer field value.
int readMatrix(const char *helpSource, int r, int c, FloatMatrix &ans)
std::string record
Record representation.
void giveRecordKeywordField(std ::string &answer, int &value) override
Reads the record id field (type of record) and its corresponding number.
void setSimpleExpression(std ::string &val)
void setReference(int val)
void setValue(double val)
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
const char * InputFieldType
Identifier of fields in input records.
Definition inputrecord.h:59

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011