FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
CHECData.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  CHECData Ver.1.0
7 */
8 
9 #include <stdarg.h>
10 #include <assert.h>
11 #include "CHECData.h"
12 #include "hecd_util.h"
13 
14 using namespace std;
15 using namespace hecd_util;
16 
17 //=============================================================================
18 // common
19 //=============================================================================
20 
22 
23 CHECData::~CHECData() { Clear(); }
24 
26  vector<CHECDataBlock *>::iterator iter;
27 
28  for (iter = DB.begin(); iter != DB.end(); iter++) {
29  delete *iter;
30  }
31 
32  DB.clear();
33 }
34 
35 void CHECData::StoreDataBlock(CHECDataBlock *block) { DB.push_back(block); }
36 
37 //=============================================================================
38 // Save
39 //=============================================================================
40 
41 bool CHECData::Save(const char *file_name) {
42  snprintf(fname, sizeof(fname), "%s", file_name);
43  fp = fopen(fname, "w");
44 
45  if (!fp) return false;
46 
47  vector<CHECDataBlock *>::iterator iter;
48 
49  for (iter = DB.begin(); iter != DB.end(); iter++) {
50  (*iter)->Write(this);
51  }
52 
53  fclose(fp);
54  fp = 0;
55  return true;
56 }
57 
58 void CHECData::WriteLine(const char *s) { fprintf(fp, "%s\n", s); }
59 
60 // ----------------------------------------------------------------------------
61 // Header Line
62 // ----------------------------------------------------------------------------
63 // fmt : format of parameters.
64 // Each character specify the parameter's type
65 // 'I': integer, 'F':float, 'S':string
66 // ... : pairs of parameter name and value
67 
68 void CHECData::WriteHeader(const char *name, const char *fmt, ...) {
69  va_list va;
70  va_start(va, fmt);
71  int n = strlen(fmt);
72  char *c = (char *)fmt;
73  char line[256];
74  char s[256];
75  size_t len = snprintf(line, sizeof(line), "%s", name);
76 
77  for (int i = 0; i < n; i++, c++) {
78  len += snprintf(line + len, sizeof(line) - len, ",%s=", va_arg(va, char *));
79 
80  switch (*c) {
81  case 'I':
82  snprintf(s, sizeof(s), "%d", va_arg(va, int));
83  break;
84 
85  case 'F':
86  // snprintf(s, sizeof(s), "%lg", va_arg(va, double));
87  ftos(va_arg(va, double), s);
88  break;
89 
90  case 'S':
91  snprintf(s, sizeof(s), "%s", va_arg(va, char *));
92  break;
93 
94  default:
95  assert(0);
96  }
97  len += snprintf(line + len, sizeof(line) - len, "%s", s);
98  }
99 
100  fprintf(fp, "%s\n", line);
101  va_end(va);
102 }
103 
104 // ----------------------------------------------------------------------------
105 // Parameter Line
106 // ----------------------------------------------------------------------------
107 
108 void CHECData::WriteParameter(const char *fmt, ...) {
109  va_list va;
110  va_start(va, fmt);
111  int n = strlen(fmt);
112  char *c = (char *)fmt;
113  char line[256];
114  char s[256];
115  size_t len = snprintf(line, sizeof(line), "!");
116 
117  for (int i = 0; i < n; i++, c++) {
118  if (i != 0) len += snprintf(line + len, sizeof(line) - len, ",");
119  len += snprintf(line + len, sizeof(line) - len, "%s=", va_arg(va, char *));
120 
121  switch (*c) {
122  case 'I':
123  snprintf(s, sizeof(s), "%d", va_arg(va, int));
124  break;
125 
126  case 'F':
127  // snprintf(s, sizeof(s), "%lg", va_arg(va, double));
128  ftos(va_arg(va, double), s);
129  break;
130 
131  case 'S':
132  snprintf(s, sizeof(s), "%s", va_arg(va, char *));
133  break;
134 
135  default:
136  assert(0);
137  }
138  len += snprintf(line + len, sizeof(line) - len, "%s", s);
139  }
140 
141  fprintf(fp, "%s\n", line);
142  va_end(va);
143 }
144 
145 // ----------------------------------------------------------------------------
146 // Data Line
147 // ----------------------------------------------------------------------------
148 // fmt : format of data like one of WriteHeader
149 // ... : values to write the file.
150 
151 void CHECData::WriteData(const char *fmt, ...) {
152  va_list va;
153  va_start(va, fmt);
154  int n = strlen(fmt);
155  char *c = (char *)fmt;
156  char line[256];
157  char s[256];
158  size_t len = 0;
159  line[0] = 0;
160 
161  for (int i = 0; i < n; i++, c++) {
162  if (i != 0) len += snprintf(line + len, sizeof(line) - len, ",");
163 
164  switch (*c) {
165  case 'I':
166  snprintf(s, sizeof(s), "%d", va_arg(va, int));
167  break;
168 
169  case 'F':
170  // snprintf(s, sizeof(s), "%lg", va_arg(va, double));
171  ftos(va_arg(va, double), s);
172  break;
173 
174  case 'S':
175  snprintf(s, sizeof(s), "%s", va_arg(va, char *));
176  break;
177 
178  default:
179  assert(0);
180  }
181  len += snprintf(line + len, sizeof(line) - len, "%s", s);
182  }
183 
184  fprintf(fp, "%s\n", line);
185  va_end(va);
186 }
187 
188 void CHECData::ClearDataLineBuffer() { data_line_buffer[0] = 0; }
189 
190 void CHECData::AddDataLineItems(const char *fmt, ...) {
191  va_list va;
192  va_start(va, fmt);
193  int n = strlen(fmt);
194  char *c = (char *)fmt;
195  char s[256];
196  size_t len = strlen(data_line_buffer);
197 
198  for (int i = 0; i < n; i++, c++) {
199  switch (*c) {
200  case 'I':
201  snprintf(s, sizeof(s), "%d", va_arg(va, int));
202  break;
203 
204  case 'F':
205  // snprintf(s, sizeof(s), "%lg", va_arg(va, double));
206  ftos(va_arg(va, double), s);
207  break;
208 
209  case 'S':
210  snprintf(s, sizeof(s), "%s", va_arg(va, char *));
211  break;
212 
213  default:
214  assert(0);
215  }
216  len += snprintf(data_line_buffer + len, sizeof(data_line_buffer) - len, "%s,", s);
217  }
218 
219  va_end(va);
220 }
221 
223  int len = strlen(data_line_buffer);
224  char *p = &data_line_buffer[len - 1];
225 
226  // remove ',' of tail
227  while (p >= data_line_buffer) {
228  if (*p == ',') {
229  *p = 0;
230  break;
231 
232  } else if (*p == ' ') {
233  *p = 0;
234 
235  } else {
236  break;
237  }
238 
239  p--;
240  }
241 
242  fprintf(fp, "%s\n", data_line_buffer);
243  ClearDataLineBuffer();
244 }
245 
246 //=============================================================================
247 // Load
248 //=============================================================================
249 
250 bool CHECData::Load(const char *file_name) {
251  Clear();
252  return AddLoad(file_name);
253 }
254 
255 bool CHECData::AddLoad(const char *file_name) {
256  line_count = 0;
257  fg_header_pushed = false;
258  snprintf(fname, sizeof(fname), "%s", file_name);
259  fp = fopen(fname, "r");
260 
261  if (!fp) return false;
262 
263  char line[256];
264  char header_name[256];
265  CHECDataBlock *block;
266 
267  while (ReadLine(line)) {
268  if (!GetHeaderName(line, header_name)) {
269  fclose(fp);
270  return false;
271  }
272 
273  if (strcmp(header_name, "!END") == 0) break;
274 
275  block = CreateDataBlock(header_name);
276 
277  if (!block) {
278  fclose(fp);
279  return false;
280  }
281 
282  if (!block->Read(this, line)) {
283  fclose(fp);
284  return false;
285  }
286 
287  DB.push_back(block);
288  }
289 
290  fclose(fp);
291  fp = 0;
292  return true;
293 }
294 
295 bool CHECData::ReadLine(char *s, int size) {
296  line_count++;
297 
298  if (fg_header_pushed) {
299  snprintf(s, size, "%s", header_line_buffer);
300  fg_header_pushed = false;
301  return true;
302  }
303 
304  while (fgets(s, size, fp)) {
305  if (s[0] == 0 || s[0] == '#' || s[0] == '\r' || s[0] == '\n') continue;
306 
307  if (s[0] == '!' && s[1] == '!') continue;
308 
309  remove_cr(s);
310  return true;
311  }
312 
313  return false;
314 }
315 
316 void CHECData::PushReadLine(const char *s) {
317  snprintf(header_line_buffer, sizeof(header_line_buffer), "%s", s);
318  fg_header_pushed = true;
319  line_count--;
320 }
321 
322 CHECDataBlock *CHECData::CreateDataBlock(const char *header_name) {
323  return CreateHECDataBlock(header_name);
324 }
325 
326 bool CHECData::GetHeaderName(const char *header_line, char *header_name) {
327 #define is_separator(x) \
328  (x == ',' || x == ' ' || x == '\t' || x == '\r' || x == '\n')
329  char *p = (char *)header_line;
330 
331  while (*p && is_separator(*p)) p++;
332 
333  if (*p != '!') return false;
334 
335  char *bp = header_name;
336 
337  while (*p && !is_separator(*p)) {
338  *bp = (char)toupper(*p);
339  p++;
340  bp++;
341  }
342 
343  *bp = 0;
344  return true;
345 #undef is_separator
346 }
347 
348 //-----------------------------------------------------------------------------
349 // ParseHeader
350 //-----------------------------------------------------------------------------
351 // rcode[i] : 1 -- set, 0 -- not set, -1 -- error
352 // fmt : string composed by following characters
353 // 'I' : int
354 // 'F' : double
355 // 'S' : char*
356 // 'E' : int (exist or not)
357 // ... : pairs of a parameter name and a pointer of the parameter
358 // example)
359 // char* line = "!SOLVER, TYPE=CG, PRECOND=1, ITERLOG=YES";
360 // int rcode[3];
361 // char type[30]; int precond; char iterlog[30];
362 // ParseHeader(line,rcode,"SIS","TYPE",type,"PRECOND",&precond,"ITERLOG",iterlog);
363 //-----------------------------------------------------------------------------
364 
365 static bool get_param_token(char *&p, char *token) {
366 #define is_separator(x) \
367  (x == ',' || x == ' ' || x == '\t' || x == '\r' || x == '\n')
368 
369  while (*p && is_separator(*p)) p++;
370 
371  if (!*p) return false;
372 
373  char *t = token;
374 
375  if (*p == '=') {
376  t[0] = '=';
377  t[1] = 0;
378  p++;
379  return true;
380  }
381 
382  while (*p && is_separator(*p)) p++;
383 
384  if (!*p) return false;
385 
386  while (*p && !is_separator(*p) && *p != '=') {
387  *t = *p;
388  t++;
389  p++;
390  }
391 
392  *t = 0;
393  return true;
394 }
395 
396 bool CHECData::vParseParameter(char *line, int *rcode, const char *fmt,
397  va_list va) {
398  const int max_param_n = 40;
399  char param_name[max_param_n][20];
400  void *param[max_param_n];
401  int param_n = strlen(fmt);
402  int i;
403  int *ip;
404 
405  for (i = 0; i < param_n; i++) {
406  snprintf(param_name[i], sizeof(param_name[i]), "%s", va_arg(va, char *));
407  param[i] = va_arg(va, void *);
408  rcode[i] = 0;
409 
410  if (fmt[i] == 'E') {
411  ip = (int *)param[i];
412  *ip = 0;
413  }
414  }
415 
416  char *p = line;
417  char p_token[50];
418  char eq_token[50];
419  char v_token[50];
420  char p_str[50];
421 
422  while (get_param_token(p, p_token)) {
423  cleanup_token(p_token, p_str);
424  toupper(p_str);
425 
426  for (i = 0; i < param_n; i++) {
427  if (strcmp(p_str, param_name[i]) == 0) break;
428  }
429 
430  if (i == param_n) return false;
431 
432  // ---------------------------------
433  if (fmt[i] == 'E') {
434  rcode[i] = 1;
435  ip = (int *)param[i];
436  *ip = 1;
437  continue;
438  }
439 
440  // ---------------------------------
441  if (!get_param_token(p, eq_token) || eq_token[0] != '=') {
442  rcode[i] = -1;
443  return false;
444  }
445 
446  if (!get_param_token(p, v_token)) {
447  rcode[i] = -1;
448  return false;
449  }
450 
451  switch (fmt[i]) {
452  case 'S':
453  if (sscanf(v_token, "%s", (char *)(param[i])) != 1) {
454  rcode[i] = -1;
455  return false;
456  }
457 
458  break;
459 
460  case 'I':
461  if (sscanf(v_token, "%d", (int *)(param[i])) != 1) {
462  rcode[i] = -1;
463  return false;
464  }
465 
466  break;
467 
468  case 'F':
469  if (sscanf(v_token, "%lf", (double *)(param[i])) != 1) {
470  rcode[i] = -1;
471  return false;
472  }
473 
474  break;
475 
476  default:
477  assert(0);
478  }
479 
480  rcode[i] = 1;
481  }
482 
483  return true;
484 }
485 
486 bool CHECData::ParseParameter(char *line, int *rcode, const char *fmt, ...) {
487  va_list va;
488  va_start(va, fmt);
489  bool fg = vParseParameter(line, rcode, fmt, va);
490  va_end(va);
491  return fg;
492 }
493 
494 bool CHECData::ParseHeader(char *header_line, int *rcode, const char *fmt,
495  ...) {
496  char *p = header_line;
497 
498  while (*p) {
499  if (*p == ',' || *p == '\r' || *p == '\n') {
500  break;
501  }
502 
503  p++;
504  }
505 
506  va_list va;
507  va_start(va, fmt);
508  bool fg = vParseParameter(p, rcode, fmt, va);
509  va_end(va);
510  return fg;
511 }
512 
513 bool CHECData::ReadParameter(int *rcode, const char *fmt, ...) {
514  char line[256];
515 
516  if (!ReadLine(line)) return false;
517 
518  char *p = line;
519 
520  if (*p == '!') p++;
521 
522  va_list va;
523  va_start(va, fmt);
524  bool fg = vParseParameter(p, rcode, fmt, va);
525  va_end(va);
526  return fg;
527 }
528 
529 //-----------------------------------------------------------------------------
530 // ReadData
531 //-----------------------------------------------------------------------------
532 // fmt : string composed by 'I', 'F' or 'S'
533 // ... : pointers of parameter
534 //-----------------------------------------------------------------------------
535 
536 bool CHECData::ReadData(int *rcode, const char *fmt, ...) {
537  char line[256];
538 
539  if (!ReadLine(line)) return false;
540 
541  if (line[0] == '!') {
542  PushReadLine(line);
543  return false;
544  }
545 
546  const int max_param_n = 100;
547  int i;
548  int param_n = strlen(fmt);
549  void *param[max_param_n];
550  va_list va;
551  va_start(va, fmt);
552 
553  for (i = 0; i < param_n; i++) {
554  param[i] = va_arg(va, void *);
555  rcode[i] = 0;
556  }
557 
558  va_end(va);
559  char *token = strtok(line, ",\r\n");
560  i = 0;
561 
562  while (token && i < param_n) {
563  switch (fmt[i]) {
564  case 'I':
565  if (sscanf(token, "%d", (int *)(param[i])) != 1) return false;
566 
567  break;
568 
569  case 'F':
570  if (sscanf(token, "%lf", (double *)(param[i])) != 1) return false;
571 
572  break;
573 
574  case 'S':
575  if (sscanf(token, "%s", (char *)(param[i])) != 1) return false;
576 
577  break;
578 
579  default:
580  assert(0);
581  }
582 
583  rcode[i] = 1;
584  token = strtok(0, ",\r\n");
585  i++;
586  }
587 
588  return true;
589 }
590 
591 int CHECData::ParseDoubleDataArray(char *line, double *data) {
592  int n = 0;
593  char *token = strtok(line, ",\r\n");
594 
595  while (token) {
596  if (sscanf(token, "%lf", &data[n]) != 1) return -(n + 1);
597 
598  n++;
599  token = strtok(0, ",\r\n");
600  }
601 
602  return n;
603 }
604 
605 int CHECData::ParseIntDataArray(char *line, int *data) {
606  int n = 0;
607  char *token = strtok(line, ",\r\n");
608 
609  while (token) {
610  if (sscanf(token, "%d", &data[n]) != 1) return -(n + 1);
611 
612  n++;
613  token = strtok(0, ",\r\n");
614  }
615 
616  return n;
617 }
618 
619 //=============================================================================
620 // Utility
621 //=============================================================================
622 
623 template <class T>
624 T hecdata_get(CHECData *hd, int data_type, const char *name) {
625  vector<CHECDataBlock *>::iterator iter;
626 
627  for (iter = hd->DB.begin(); iter != hd->DB.end(); iter++) {
628  if ((*iter)->data_type == data_type) {
629  T block = (T)(*iter);
630 
631  if (strcmp(block->name, name) == 0) {
632  return block;
633  }
634  }
635  }
636 
637  return 0;
638 }
639 
641  return hecdata_get<CHECDB_Material *>(this, HECDB_MATERIAL, name);
642 }
643 
644 CHECDB_NGroup *CHECData::GetNGroup(const char *name) {
645  return hecdata_get<CHECDB_NGroup *>(this, HECDB_NGROUP, name);
646 }
647 
648 CHECDB_EGroup *CHECData::GetEGroup(const char *name) {
649  return hecdata_get<CHECDB_EGroup *>(this, HECDB_EGROUP, name);
650 }
651 
652 CHECDB_SGroup *CHECData::GetSGroup(const char *name) {
653  return hecdata_get<CHECDB_SGroup *>(this, HECDB_SGROUP, name);
654 }
655 
657  vector<CHECDataBlock *>::iterator iter;
658 
659  for (iter = DB.begin(); iter != DB.end(); iter++) {
660  if ((*iter)->data_type != HECDB_NODE) continue;
661 
662  CHECDB_Node::CNodeItem *nitem = ((CHECDB_Node *)(*iter))->GetNode(id);
663 
664  if (nitem) return nitem;
665  }
666 
667  return 0;
668 }
669 
671  vector<CHECDataBlock *>::iterator iter;
672 
673  for (iter = DB.begin(); iter != DB.end(); iter++) {
674  if ((*iter)->data_type != HECDB_ELEMENT) continue;
675 
676  CHECDB_Element::CElemItem *eitem = ((CHECDB_Element *)(*iter))->GetElem(id);
677 
678  if (eitem) return eitem;
679  }
680 
681  return 0;
682 }
683 
685  vector<CHECDataBlock *>::iterator iter;
686 
687  for (iter = DB.begin(); iter != DB.end(); iter++) {
688  if ((*iter)->data_type != HECDB_ELEMENT) continue;
689 
690  CHECDB_Element::CElemItem *eitem = ((CHECDB_Element *)(*iter))->GetElem(id);
691 
692  if (eitem) return ((CHECDB_Element *)(*iter))->type;
693  }
694 
695  return 0;
696 }
@ HECDB_EGROUP
Definition: CHECDB.h:24
@ HECDB_MATERIAL
Definition: CHECDB.h:21
@ HECDB_NODE
Definition: CHECDB.h:19
@ HECDB_SGROUP
Definition: CHECDB.h:25
@ HECDB_ELEMENT
Definition: CHECDB.h:20
@ HECDB_NGROUP
Definition: CHECDB.h:23
CHECDataBlock * CreateHECDataBlock(const char *header_name)
Definition: HECDB_util.cpp:16
#define is_separator(x)
T hecdata_get(CHECData *hd, int data_type, const char *name)
Definition: CHECData.cpp:624
virtual bool Read(class CHECData *hecd, char *header_line)=0
virtual int ParseIntDataArray(char *line, int *data)
Definition: CHECData.cpp:605
virtual void WriteDataLine()
Definition: CHECData.cpp:222
virtual class CHECDB_Node::CNodeItem * GetNodeItem(int id)
Definition: CHECData.cpp:656
virtual bool ReadData(int *rcode, const char *fmt,...)
Definition: CHECData.cpp:536
virtual void WriteParameter(const char *fmt="",...)
Definition: CHECData.cpp:108
virtual ~CHECData()
Definition: CHECData.cpp:23
virtual bool ParseParameter(char *line, int *rcode, const char *fmt,...)
Definition: CHECData.cpp:486
virtual int GetElemType(int id)
Definition: CHECData.cpp:684
virtual bool vParseParameter(char *line, int *rcode, const char *fmt, va_list va)
Definition: CHECData.cpp:396
virtual class CHECDB_SGroup * GetSGroup(const char *name)
Definition: CHECData.cpp:652
virtual int ParseDoubleDataArray(char *line, double *data)
Definition: CHECData.cpp:591
virtual bool Save(const char *file_name)
Definition: CHECData.cpp:41
virtual bool ParseHeader(char *header_line, int *rcode, const char *fmt,...)
Definition: CHECData.cpp:494
std::vector< CHECDataBlock * > DB
Definition: CHECData.h:30
virtual bool AddLoad(const char *file_name)
Definition: CHECData.cpp:255
virtual void Clear()
Definition: CHECData.cpp:25
virtual void StoreDataBlock(CHECDataBlock *block)
Definition: CHECData.cpp:35
CHECData()
Definition: CHECData.cpp:21
virtual bool Load(const char *file_name)
Definition: CHECData.cpp:250
virtual class CHECDB_Element::CElemItem * GetElemItem(int id)
Definition: CHECData.cpp:670
virtual void WriteData(const char *fmt,...)
Definition: CHECData.cpp:151
virtual class CHECDB_Material * GetMaterial(const char *name)
Definition: CHECData.cpp:640
virtual bool ReadLine(char *s, int size=256)
Definition: CHECData.cpp:295
virtual bool ReadParameter(int *rcode, const char *fmt,...)
Definition: CHECData.cpp:513
virtual void WriteHeader(const char *name, const char *fmt="",...)
Definition: CHECData.cpp:68
virtual void ClearDataLineBuffer()
Definition: CHECData.cpp:188
virtual void AddDataLineItems(const char *fmt,...)
Definition: CHECData.cpp:190
virtual class CHECDB_EGroup * GetEGroup(const char *name)
Definition: CHECData.cpp:648
virtual class CHECDB_NGroup * GetNGroup(const char *name)
Definition: CHECData.cpp:644
virtual void WriteLine(const char *s)
Definition: CHECData.cpp:58
virtual void PushReadLine(const char *s)
Definition: CHECData.cpp:316
virtual bool GetHeaderName(const char *header_line, char *header_name)
Definition: CHECData.cpp:326
virtual CHECDataBlock * CreateDataBlock(const char *header_name)
Definition: CHECData.cpp:322
void toupper(char *s)
Definition: hecd_util.cpp:38
void cleanup_token(char *s)
Definition: hecd_util.cpp:13
void remove_cr(char *s)
Definition: hecd_util.cpp:76
void ftos(double x, char *s)
Definition: hecd_util.cpp:91
CNFData data