FrontISTR  5.7.0
Large-scale structural analysis program with finit element method
CNFData.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright (c) 2019 FrontISTR Commons
3  * This software is released under the MIT License, see LICENSE.txt
4  *****************************************************************************/
5 /*
6  CNFData Ver.1.0
7 */
8 
9 #include <stdarg.h>
10 
11 #include "CNFData.h"
12 
13 using namespace std;
14 
16  neu_file[0] = 0;
17  title[0] = 0;
18  log_fp = stdout;
19 }
20 
21 CNFData::CNFData(const char *fname)
22  : version(DefaultCNFDataVersion), fp(0), line(0) {
23  title[0] = 0;
24  log_fp = stdout;
25  Load(fname);
26 }
27 
29 
31 #define GENRATE_CODE(x) Clear_##x();
32  GENRATE_CODE(402)
33  GENRATE_CODE(403)
34  GENRATE_CODE(404)
35  GENRATE_CODE(405)
36  GENRATE_CODE(408)
37  GENRATE_CODE(506)
38  GENRATE_CODE(507)
39  GENRATE_CODE(601)
40 #undef GENRATE_CODE
42 }
43 
44 #define GENRATE_CODE(x) \
45  void CNFData::Clear_##x() { \
46  vector<CNFDB_##x *>::iterator iter; \
47  for (iter = DB_##x.begin(); iter != DB_##x.end(); iter++) delete *iter; \
48  DB_##x.clear(); \
49  }
50 
51 GENRATE_CODE(402)
52 GENRATE_CODE(403)
53 GENRATE_CODE(404)
54 GENRATE_CODE(405)
55 GENRATE_CODE(408)
56 GENRATE_CODE(506)
57 GENRATE_CODE(507)
58 GENRATE_CODE(601)
59 
60 #undef GENRATE_CODE
61 
62 //*****************************************************************************
63 // Load
64 //*****************************************************************************
65 
66 void CNFData::Load(const char *fname) {
67  char buff[256];
68  nf_int BlockID;
69  CNFDataBlock *block;
70  int fg_block_continue;
71  strcpy(neu_file, fname);
72  fp = fopen(fname, "r");
73 
74  if (!fp) {
75  char s[256];
76  sprintf(s, ": %s", fname);
77  throw CNFError(NFE_OPEN_ERROR, s);
78  }
79 
82  line = 0;
83 
84  try {
85  while (!EndOfFile()) {
86  int rcode = ReadLine(buff);
87 
88  if (rcode == READLINE_EOF) {
89  break;
90 
91  } else if (rcode == READLINE_ERROR) {
93 
94  } else if (rcode != READLINE_SEPARATOR) {
96  }
97 
98  ReadLineEx(buff);
99  ReadRecord(buff, "I", &BlockID);
100 
101  do {
102  block = CreateDataBlock(BlockID);
103 
104  if (block) {
105  fprintf(log_fp, "line:%d reading block %d\n", (int)line,
106  (int)BlockID);
107 
108  if (ReadLine(buff) == READLINE_SUCESS) {
109  PushBackLine(buff);
110  block->Read(this);
111  StoreDataBlock(block);
112 
113  if (ReadLine(buff) != READLINE_SEPARATOR) {
114  PushBackLine(buff);
115  fg_block_continue = TRUE;
116 
117  } else {
118  fg_block_continue = FALSE;
119  }
120 
121  } else {
122  fprintf(log_fp, " ---- blank block\n");
123  delete block;
124  fg_block_continue = FALSE;
125  }
126 
127  } else {
128  non_supported_block_list.insert(BlockID);
129  char s[256];
130  sprintf(s, ": %d", (int)BlockID);
132  PrintMessage(w.Msg());
133  SkipDataBlock();
134  fg_block_continue = FALSE;
135  }
136  } while (fg_block_continue);
137  }
138 
139  } catch (CNFError e) {
140  fclose(fp);
141  throw e;
142  }
143 
144  fclose(fp);
145  fprintf(log_fp, "Data reading completed!\n");
146 }
147 
148 //*****************************************************************************
149 // Save
150 //*****************************************************************************
151 
152 void CNFData::Save(const char *fname) {
153  strcpy(neu_file, fname);
154  fp = fopen(fname, "w");
155 
156  if (!fp) {
157  char s[256];
158  sprintf(s, ": %s", fname);
159  throw CNFError(NFE_OPEN_ERROR, s);
160  }
161 
162 #define GENRATE_CODE(x) \
163  if (!CNFData::WriteDataBlock(fp, x)) { \
164  fclose(fp); \
165  throw CNFError(NFE_WRITEDATA_ERROR); \
166  }
167  GENRATE_CODE(100)
168  GENRATE_CODE(402)
169  GENRATE_CODE(403)
170  GENRATE_CODE(404)
171  GENRATE_CODE(405)
172  GENRATE_CODE(408)
173  GENRATE_CODE(506)
174  GENRATE_CODE(507)
175  GENRATE_CODE(601)
176 #undef GENRATE_CODE
177  fclose(fp);
178 }
179 
180 //*****************************************************************************
181 // DataBlock Utilities
182 //*****************************************************************************
183 
185 #define GENRATE_CODE(x) \
186  case x: \
187  return new CNFDB_##x;
188 
189  switch (BlockID) {
190  GENRATE_CODE(100)
191  GENRATE_CODE(402)
192  GENRATE_CODE(403)
193  GENRATE_CODE(404)
194  GENRATE_CODE(405)
195  GENRATE_CODE(408)
196  GENRATE_CODE(506)
197  GENRATE_CODE(507)
198  GENRATE_CODE(601)
199 
200  default:
201  return NULL;
202  }
203 
204 #undef GENRATE_CODE
205 }
206 
208 #define GENRATE_CODE(x) \
209  case x: \
210  DB_##x.push_back((CNFDB_##x *)block); \
211  break;
212 
213  switch (block->DataBlockID) {
214  case 100:
215  version = ((CNFDB_100 *)block)->version;
216  strcpy(title, ((CNFDB_100 *)block)->title);
217  delete block;
218  break;
219  GENRATE_CODE(402)
220  GENRATE_CODE(403)
221  GENRATE_CODE(404)
222  GENRATE_CODE(405)
223  GENRATE_CODE(408)
224  GENRATE_CODE(506)
225  GENRATE_CODE(507)
226  GENRATE_CODE(601)
227 
228  default:
229  assert(0);
230  }
231 
232 #undef GENRATE_CODE
233 }
234 
236  char buff[256];
237 
238  while (!EndOfFile()) {
239  if (ReadLine(buff) == READLINE_SEPARATOR) return;
240  }
241 }
242 
243 //*****************************************************************************
244 // Utilities
245 //*****************************************************************************
246 
247 void CNFData::PrintMessage(const char *msg) {
248  fprintf(stdout, "%s\n", msg);
249 
250  if (stdout != log_fp) fprintf(log_fp, "%s\n", msg);
251 
252  fflush(stdout);
253 }
254 
255 //*****************************************************************************
256 // Basic Input Method
257 //*****************************************************************************
258 
259 void CNFData::ReadRecStart(char *buff) {
260  strcpy(rec_buff, buff);
261  fg_rec_first = TRUE;
262  rec_column = 0;
263 }
264 
265 int CNFData::ReadRecNext(char type, void *value) {
266  rec_column++;
267  char *token;
268 
269  if (fg_rec_first) {
270  token = strtok(rec_buff, ",\n\r");
271  fg_rec_first = false;
272 
273  } else {
274  token = strtok(NULL, ",\n\r");
275  }
276 
277  if (!token) return FALSE;
278 
279  switch (type) {
280  case 'I':
281  if (sscanf(token, "%d", (int *)value) != 1) {
283  }
284 
285  break;
286 
287  case 'B':
288  if (sscanf(token, "%hhd", (unsigned char *)value) != 1) {
290  }
291 
292  break;
293 
294  case 'F':
295  if (sscanf(token, "%lf", (double *)value) != 1) {
297  }
298 
299  break;
300 
301  default:
302  assert(0);
303  }
304 
305  return TRUE;
306 }
307 
308 void CNFData::ReadRecord(char *buff, const char *fmt, ...) {
309  va_list va;
310  va_start(va, fmt);
311  int n = strlen(fmt);
312  void *val_ptr[200];
313  assert(!(n > 200));
314 
315  for (int i = 0; i < n; i++) {
316  val_ptr[i] = (void *)va_arg(va, void *);
317  }
318 
319  va_end(va);
320 
321  try {
322  ReadRecStart(buff);
323  char *c = (char *)fmt;
324 
325  for (int i = 0; i < n; i++, c++) {
326  if (!ReadRecNext(*c, val_ptr[i])) {
327  throw CNFError(NFE_ITEM_REQUIRED, line, i + 1);
328  }
329  }
330 
331  } catch (CNFError err) {
332  throw err;
333  }
334 }
335 
336 int CNFData::ReadLine(char *buff, int size) {
337  if (!fg_line_buff_empty) {
338  strcpy(buff, line_buff);
340  return READLINE_SUCESS;
341  }
342 
343  do {
344  line++;
345 
346  if (!fgets(buff, size, fp)) return READLINE_EOF;
347 
348  char *p = buff;
349 
350  while (*p) {
351  if (*p == '\r' || *p == '\n') {
352  *p = 0;
353  break;
354  }
355 
356  p++;
357  }
358  } while (buff[0] == 0);
359 
360  if (strcmp(buff, " -1") == 0) {
361  return READLINE_SEPARATOR;
362  }
363 
364  return READLINE_SUCESS;
365 }
366 
367 void CNFData::ReadLineEx(char *buff, int size) {
368  if (ReadLine(buff, size) != READLINE_SUCESS) {
370  }
371 }
372 
373 void CNFData::ReadStr(char *buff, char *s, int size) {
374  int i;
375 
376  if (strcmp(buff, "<NULL>") == 0) {
377  s[0] = 0;
378  return;
379  }
380 
381  int n = strlen(buff);
382  assert(!(n >= size));
383 
384  for (i = 0; i < n; i++) s[i] = buff[i];
385 
386  s[i] = 0;
387 }
388 
389 void CNFData::PushBackLine(char *buff) {
390  strcpy(line_buff, buff);
392 }
393 
394 void CNFData::ReadMultRec(char type, int n_in_rec, int val_n, void *val) {
395  char buff[256];
396  int i, j, n, id, end_id;
397  char *p = (char *)val;
398  int size;
399 
400  switch (type) {
401  case 'I':
402  size = sizeof(nf_int);
403  break;
404 
405  case 'F':
406  size = sizeof(nf_float);
407  break;
408 
409  case 'B':
410  size = sizeof(nf_bool);
411  break;
412 
413  default:
414  assert(0);
415  }
416 
417  n = val_n / n_in_rec;
418  id = 0;
419 
420  for (i = 0; i < n; i++) {
421  ReadLineEx(buff);
422  ReadRecStart(buff);
423  j = 0;
424  end_id = id + n_in_rec;
425 
426  for (; id < end_id; id++, j++) {
427  if (!ReadRecNext(type, p)) {
428  throw CNFError(NFE_ITEM_REQUIRED, line, j + 1);
429  }
430 
431  p += size;
432  }
433  }
434 
435  if (id < val_n) {
436  ReadLineEx(buff);
437  ReadRecStart(buff);
438  j = 0;
439 
440  for (; id < val_n; id++, j++) {
441  if (!ReadRecNext(type, p)) {
442  throw CNFError(NFE_ITEM_REQUIRED, line, j + 1);
443  }
444 
445  p += size;
446  }
447  }
448 }
449 
450 //-----------------------------------------------------------------------------
451 
452 void CNFData::WriteStr(FILE *fp, const char *s) {
453  if (s == 0 || s[0] == 0) {
454  fprintf(fp, "<NULL>\n");
455 
456  } else {
457  fprintf(fp, "%s\n", s);
458  }
459 }
460 
461 static void float_write(FILE *fp, double x) {
462  fprintf(fp, "%lg,", x);
463  /*******************************************
464  if( x != 0.0 && -1e-4 <= x && x <= 1e-4 ){
465  fprintf(fp, "%le,", x );
466  return;
467  }
468 
469  char buff[256];
470  sprintf(buff, "%lf", x);
471 
472  char* p = &buff[strlen(buff)-1];
473  while( buff < p && *p == '0') p--;
474  char* zp = p;
475  zp++;
476  while( buff < p && *p != '.') p--;
477 
478  if( *p == '.' ) {
479  *zp = 0;
480  }
481 
482  fprintf(fp, "%s,", buff);
483  ********************************************/
484 }
485 
486 void CNFData::WriteData(FILE *fp, const char *fmt, ...) {
487  va_list va;
488  va_start(va, fmt);
489  int n = strlen(fmt);
490  int b;
491  double x;
492 
493  try {
494  char *c = (char *)fmt;
495 
496  for (int i = 0; i < n; i++, c++) {
497  switch (*c) {
498  case 'n':
499  case 'N':
500  fprintf(fp, "\n");
501  break;
502 
503  case 'i':
504  case 'I':
505  fprintf(fp, "%d,", (int)(va_arg(va, nf_int)));
506  break;
507 
508  case 'b':
509  case 'B':
510  b = va_arg(va, nf_int);
511  fprintf(fp, "%d,", b);
512  break;
513 
514  case 'f':
515  case 'F':
516  x = va_arg(va, nf_float);
517  float_write(fp, x);
518  break;
519 
520  default:
521  assert(0);
522  }
523  }
524 
525  } catch (CNFError err) {
526  va_end(va);
527  throw err;
528  }
529 
530  va_end(va);
531 }
532 
533 void CNFData::WriteBlockSeparator(FILE *fp) { fprintf(fp, " -1\n"); }
534 
535 bool CNFData::WriteDataBlock(FILE *fp, int id) {
536 #define GENRATE_CODE(x) \
537  case (x): { \
538  if (DB_##x.size() > 0) { \
539  WriteBlockSeparator(fp); \
540  fprintf(fp, " %d\n", (x)); \
541  vector<CNFDB_##x *>::iterator iter; \
542  for (iter = DB_##x.begin(); iter != DB_##x.end(); iter++) \
543  (*iter)->WriteData(this, fp); \
544  WriteBlockSeparator(fp); \
545  } \
546  break; \
547  }
548 
549  switch (id) {
550  case 100: {
551  CNFDB_100 DB100;
552  DB100.version = version;
553  strcpy(DB100.title, title);
555  fprintf(fp, " 100\n");
556 
557  DB100.WriteData(this, fp);
559  } break;
560  GENRATE_CODE(402)
561  GENRATE_CODE(403)
562  GENRATE_CODE(404)
563  GENRATE_CODE(405)
564  GENRATE_CODE(408)
565  GENRATE_CODE(506)
566  GENRATE_CODE(507)
567  GENRATE_CODE(601)
568 
569  default:
570  return false;
571  }
572 
573 #undef GENRATE_CODE
574  return true;
575 }
576 
577 //*****************************************************************************
578 // Report Status
579 //*****************************************************************************
580 
581 void CNFData::WriteSummary(FILE *fp) {
582  if (!fp) fp = stdout;
583 
584  fprintf(fp, "%8s %8s\n", "BlockID", "num");
585  fprintf(fp, "====================\n");
586 #define GENRATE_CODE(x) \
587  if ((DB_##x).size() > 0) fprintf(fp, "%8d %8lu\n", (x), (DB_##x).size());
588  GENRATE_CODE(402)
589  GENRATE_CODE(403)
590  GENRATE_CODE(404)
591  GENRATE_CODE(405)
592  GENRATE_CODE(408)
593  GENRATE_CODE(506)
594  GENRATE_CODE(507)
595  GENRATE_CODE(601)
596 #undef GENRATE_CODE
597  fprintf(fp, "====================\n\n");
598  fprintf(fp, "non supporting block (skipped)\n");
599  int i = 0;
600  set<int>::iterator iter;
601 
602  for (iter = non_supported_block_list.begin();
603  iter != non_supported_block_list.end(); iter++) {
604  if (i == 10) {
605  fprintf(fp, "\n");
606  i = 0;
607  }
608 
609  fprintf(fp, " %4d,", *iter);
610  i++;
611  }
612 
613  fprintf(fp, "\n");
614  fflush(fp);
615 }
CNFData::ReadRecord
void ReadRecord(char *buff, const char *fmt,...)
Definition: CNFData.cpp:308
CNFDB_100::WriteData
virtual void WriteData(class CNFData *nfd, FILE *fp)
Definition: CNFDB_100.cpp:31
GENRATE_CODE
#define GENRATE_CODE(x)
Definition: CNFData.cpp:44
CNFData::non_supported_block_list
std::set< int > non_supported_block_list
Definition: CNFData.h:125
CNFData::log_fp
FILE * log_fp
Definition: CNFData.h:90
CNFDataBlock::Read
virtual void Read(class CNFData *nfd)=0
CNFData::WriteBlockSeparator
void WriteBlockSeparator(FILE *fp)
Definition: CNFData.cpp:533
NFE_READDATA_ERROR
@ NFE_READDATA_ERROR
Definition: CNFMessage.h:23
version
void version(char *arg)
show version and revision of FrontISTR
Definition: main.c:243
CNFData::StoreDataBlock
virtual void StoreDataBlock(CNFDataBlock *block)
Definition: CNFData.cpp:207
CNFDataBlock
Definition: CNFDataBlock.h:24
CNFData::line
int line
Definition: CNFData.h:92
CNFData::fg_rec_first
int fg_rec_first
Definition: CNFData.h:119
NFE_DATA_BLOCK_REQUIRED
@ NFE_DATA_BLOCK_REQUIRED
Definition: CNFMessage.h:25
CNFData::WriteStr
void WriteStr(FILE *fp, const char *s)
Definition: CNFData.cpp:452
NFE_ITEM_REQUIRED
@ NFE_ITEM_REQUIRED
Definition: CNFMessage.h:27
CNFData.h
CNFData::Clear
virtual void Clear()
Definition: CNFData.cpp:30
CNFDB_100::title
nf_char title[256]
Definition: CNFDB_100.h:30
CNFWarning
Definition: CNFMessage.h:60
CNFData::version
double version
Definition: CNFData.h:48
READLINE_ERROR
const int READLINE_ERROR
Definition: CNFData.h:40
CNFData::Save
virtual void Save(const char *fname)
Definition: CNFData.cpp:152
CNFData::ReadRecStart
void ReadRecStart(char *buff)
Definition: CNFData.cpp:259
NFW_NON_SUPPORTED_DATA_BLOCK
@ NFW_NON_SUPPORTED_DATA_BLOCK
Definition: CNFMessage.h:31
CNFData::PrintMessage
virtual void PrintMessage(const char *msg)
Definition: CNFData.cpp:247
CNFData::PushBackLine
void PushBackLine(char *buff)
Definition: CNFData.cpp:389
CNFData::fp
FILE * fp
Definition: CNFData.h:91
CNFData::line_buff
char line_buff[512]
Definition: CNFData.h:93
CNFWarning::Msg
virtual const char * Msg()
Definition: CNFMessage.cpp:43
READLINE_EOF
const int READLINE_EOF
Definition: CNFData.h:39
READLINE_SUCESS
const int READLINE_SUCESS
Definition: CNFData.h:37
READLINE_SEPARATOR
const int READLINE_SEPARATOR
Definition: CNFData.h:38
CNFData::WriteDataBlock
bool WriteDataBlock(FILE *fp, int id)
Definition: CNFData.cpp:535
CNFData::ReadLine
int ReadLine(char *buff, int size=255)
Definition: CNFData.cpp:336
CNFData::ReadLineEx
void ReadLineEx(char *buff, int size=255)
Definition: CNFData.cpp:367
CNFData::ReadMultRec
void ReadMultRec(char type, int n_in_rec, int val_n, void *val)
Definition: CNFData.cpp:394
CNFData::CreateDataBlock
virtual CNFDataBlock * CreateDataBlock(int block_id)
Definition: CNFData.cpp:184
CNFData::WriteData
void WriteData(FILE *fp, const char *fmt,...)
Definition: CNFData.cpp:486
CNFData::WriteSummary
void WriteSummary(FILE *fp=0)
Definition: CNFData.cpp:581
FALSE
#define FALSE
Definition: fstr_ctrl_util.c:13
CNFData::ReadStr
void ReadStr(char *buff, char *s, int size)
Definition: CNFData.cpp:373
CNFData::~CNFData
virtual ~CNFData()
Definition: CNFData.cpp:28
CNFData::Load
virtual void Load(const char *fname)
Definition: CNFData.cpp:66
nf_bool
unsigned char nf_bool
Definition: CNFDataBlock.h:20
CNFData::title
char title[256]
Definition: CNFData.h:49
CNFError
Definition: CNFMessage.h:51
CNFDataBlock::DataBlockID
int DataBlockID
Definition: CNFDataBlock.h:26
CNFData::SkipDataBlock
virtual void SkipDataBlock()
Definition: CNFData.cpp:235
NFE_INVALID_TOKEN
@ NFE_INVALID_TOKEN
Definition: CNFMessage.h:26
CNFData::CNFData
CNFData()
Definition: CNFData.cpp:15
CNFData::EndOfFile
int EndOfFile()
Definition: CNFData.h:96
DefaultCNFDataVersion
const double DefaultCNFDataVersion
Definition: CNFData.h:34
CNFDB_100::version
nf_float version
Definition: CNFDB_100.h:32
NFE_OPEN_ERROR
@ NFE_OPEN_ERROR
Definition: CNFMessage.h:22
CNFData::ReadRecNext
int ReadRecNext(char type, void *value)
Definition: CNFData.cpp:265
CNFData::fg_line_buff_empty
int fg_line_buff_empty
Definition: CNFData.h:94
nf_int
int nf_int
Definition: CNFDataBlock.h:19
NULL
#define NULL
Definition: hecmw_io_nastran.c:30
CNFData::rec_buff
char rec_buff[256]
Definition: CNFData.h:118
TRUE
#define TRUE
Definition: fstr_ctrl_util.c:12
CNFData::neu_file
char neu_file[256]
Definition: CNFData.h:89
CNFDB_100
Definition: CNFDB_100.h:17
CNFData::rec_column
int rec_column
Definition: CNFData.h:120
NFE_LINE_REQUIRED
@ NFE_LINE_REQUIRED
Definition: CNFMessage.h:24
nf_float
double nf_float
Definition: CNFDataBlock.h:21