FrontISTR 5.2.0
Large-scale structural analysis program with finit element method
Loading...
Searching...
No Matches
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
13using namespace std;
14
16 neu_file[0] = 0;
17 title[0] = 0;
18 log_fp = stdout;
19}
20
21CNFData::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
51GENRATE_CODE(402)
52GENRATE_CODE(403)
53GENRATE_CODE(404)
54GENRATE_CODE(405)
55GENRATE_CODE(408)
56GENRATE_CODE(506)
57GENRATE_CODE(507)
58GENRATE_CODE(601)
59
60#undef GENRATE_CODE
61
62//*****************************************************************************
63// Load
64//*****************************************************************************
65
66void 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());
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
152void 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
247void 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
259void CNFData::ReadRecStart(char *buff) {
260 strcpy(rec_buff, buff);
262 rec_column = 0;
263}
264
265int 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
308void 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
336int 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
367void CNFData::ReadLineEx(char *buff, int size) {
368 if (ReadLine(buff, size) != READLINE_SUCESS) {
370 }
371}
372
373void 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
389void CNFData::PushBackLine(char *buff) {
390 strcpy(line_buff, buff);
392}
393
394void 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
452void 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
461static 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
486void 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
533void CNFData::WriteBlockSeparator(FILE *fp) { fprintf(fp, " -1\n"); }
534
535bool 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
581void 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}
#define GENRATE_CODE(x)
Definition: CNFData.cpp:44
const double DefaultCNFDataVersion
Definition: CNFData.h:34
const int READLINE_EOF
Definition: CNFData.h:39
const int READLINE_ERROR
Definition: CNFData.h:40
#define TRUE
Definition: CNFData.h:13
#define FALSE
Definition: CNFData.h:14
const int READLINE_SUCESS
Definition: CNFData.h:37
const int READLINE_SEPARATOR
Definition: CNFData.h:38
#define GENRATE_CODE(x)
Definition: CNFData.h:65
int nf_int
Definition: CNFDataBlock.h:19
unsigned char nf_bool
Definition: CNFDataBlock.h:20
double nf_float
Definition: CNFDataBlock.h:21
@ NFE_INVALID_TOKEN
Definition: CNFMessage.h:23
@ NFE_LINE_REQUIRED
Definition: CNFMessage.h:21
@ NFE_DATA_BLOCK_REQUIRED
Definition: CNFMessage.h:22
@ NFE_READDATA_ERROR
Definition: CNFMessage.h:20
@ NFE_ITEM_REQUIRED
Definition: CNFMessage.h:24
@ NFE_OPEN_ERROR
Definition: CNFMessage.h:19
@ NFW_NON_SUPPORTED_DATA_BLOCK
Definition: CNFMessage.h:31
virtual void WriteData(class CNFData *nfd, FILE *fp)
Definition: CNFDB_100.cpp:31
nf_float version
Definition: CNFDB_100.h:29
nf_char title[256]
Definition: CNFDB_100.h:27
virtual void Read(class CNFData *nfd)=0
int fg_rec_first
Definition: CNFData.h:119
int ReadRecNext(char type, void *value)
Definition: CNFData.cpp:265
char title[256]
Definition: CNFData.h:49
virtual CNFDataBlock * CreateDataBlock(int block_id)
Definition: CNFData.cpp:184
void WriteStr(FILE *fp, const char *s)
Definition: CNFData.cpp:452
int rec_column
Definition: CNFData.h:120
void ReadStr(char *buff, char *s, int size)
Definition: CNFData.cpp:373
bool WriteDataBlock(FILE *fp, int id)
Definition: CNFData.cpp:535
virtual void Save(const char *fname)
Definition: CNFData.cpp:152
int fg_line_buff_empty
Definition: CNFData.h:94
CNFData()
Definition: CNFData.cpp:15
std::set< int > non_supported_block_list
Definition: CNFData.h:125
virtual void PrintMessage(const char *msg)
Definition: CNFData.cpp:247
void ReadLineEx(char *buff, int size=255)
Definition: CNFData.cpp:367
double version
Definition: CNFData.h:48
virtual void SkipDataBlock()
Definition: CNFData.cpp:235
int line
Definition: CNFData.h:92
virtual void StoreDataBlock(CNFDataBlock *block)
Definition: CNFData.cpp:207
void WriteBlockSeparator(FILE *fp)
Definition: CNFData.cpp:533
int EndOfFile()
Definition: CNFData.h:96
void WriteData(FILE *fp, const char *fmt,...)
Definition: CNFData.cpp:486
void PushBackLine(char *buff)
Definition: CNFData.cpp:389
char line_buff[512]
Definition: CNFData.h:93
virtual void Clear()
Definition: CNFData.cpp:30
void ReadRecord(char *buff, const char *fmt,...)
Definition: CNFData.cpp:308
char rec_buff[256]
Definition: CNFData.h:118
virtual ~CNFData()
Definition: CNFData.cpp:28
FILE * fp
Definition: CNFData.h:91
FILE * log_fp
Definition: CNFData.h:90
void WriteSummary(FILE *fp=0)
Definition: CNFData.cpp:581
void ReadRecStart(char *buff)
Definition: CNFData.cpp:259
virtual void Load(const char *fname)
Definition: CNFData.cpp:66
void ReadMultRec(char type, int n_in_rec, int val_n, void *val)
Definition: CNFData.cpp:394
int ReadLine(char *buff, int size=255)
Definition: CNFData.cpp:336
char neu_file[256]
Definition: CNFData.h:89
virtual const char * Msg()
Definition: CNFMessage.cpp:43
#define NULL
void version(char *arg)
show version and revision of FrontISTR
Definition: main.c:117