Salome HOME
Adding support for int64 field in basic api
[tools/medcoupling.git] / src / MEDLoader / libmesh5.cxx
1 /*----------------------------------------------------------*/
2 /*                                                                                                                      */
3 /*                                              LIBMESH V 5.46                                          */
4 /*                                                                                                                      */
5 /*----------------------------------------------------------*/
6 /*                                                                                                                      */
7 /*      Description:            handle .meshb file format I/O           */
8 /*      Author:                         Loic MARECHAL                                           */
9 /*      Creation date:          feb 16 2007                                                     */
10 /*      Last modification:      apr 03 2012                                                     */
11 /*                                                                                                                      */
12 /*----------------------------------------------------------*/
13
14
15 /*----------------------------------------------------------*/
16 /* Includes                                                                                                     */
17 /*----------------------------------------------------------*/
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <string.h>
23 #include <float.h>
24 #include <math.h>
25 #include <ctype.h>
26 #include "libmesh5.hxx"
27 #ifdef WIN32
28 #include <windows.h>
29 #endif
30
31 using namespace MeshFormat;
32
33
34
35 /*----------------------------------------------------------*/
36 /* Global variables                                                                                     */
37 /*----------------------------------------------------------*/
38
39 // see MeshGems/Docs/meshgems_formats_description.pdf
40 const char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] =
41 {   {"Reserved", "", "", ""},
42     {"MeshVersionFormatted", "", "", "i"},
43     {"Reserved", "", "", ""},
44     {"Dimension", "", "", "i"},
45     {"Vertices", "Vertex", "i", "dri"},
46     {"Edges", "Edge", "i", "iii"},
47     {"Triangles", "Triangle", "i", "iiii"},
48     {"Quadrilaterals", "Quadrilateral", "i", "iiiii"},
49     {"Tetrahedra", "Tetrahedron", "i", "iiiii"},
50     {"Prisms", "Prism", "i", "iiiiiii"},
51     {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"},
52     {"IterationsAll", "IterationAll","","i"},
53     {"TimesAll", "TimeAll","","r"},
54     {"Corners", "Corner", "i", "i"},
55     {"Ridges", "Ridge", "i", "i"},
56     {"RequiredVertices", "RequiredVertex", "i", "i"},
57     {"RequiredEdges", "RequiredEdge", "i", "i"},
58     {"RequiredTriangles", "RequiredTriangle", "i", "i"},
59     {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"},
60     {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"},
61     {"NormalAtVertices", "NormalAtVertex", "i", "ii"},
62     {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"},
63     {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"},
64     {"AngleOfCornerBound", "", "", "r"},
65     {"TrianglesP2", "TriangleP2", "i", "iiiiiii"},
66     {"EdgesP2", "EdgeP2", "i", "iiii"},
67     {"SolAtPyramids", "SolAtPyramid", "i", "sr"},
68     {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"},
69     {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"},
70     {"SubDomainFromGeom", "SubDomainFromGeom", "i", "iiii"},
71     {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"},
72     {"Fault_NearTri", "Fault_NearTri", "i", "i"},
73     {"Fault_Inter", "Fault_Inter", "i", "i"},
74     {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"},
75     {"ExtraVerticesAtEdges", "ExtraVerticesAtEdge", "i", "in"},
76     {"ExtraVerticesAtTriangles", "ExtraVerticesAtTriangle", "i", "in"},
77     {"ExtraVerticesAtQuadrilaterals", "ExtraVerticesAtQuadrilateral", "i", "in"},
78     {"ExtraVerticesAtTetrahedra", "ExtraVerticesAtTetrahedron", "i", "in"},
79     {"ExtraVerticesAtPrisms", "ExtraVerticesAtPrism", "i", "in"},
80     {"ExtraVerticesAtHexahedra", "ExtraVerticesAtHexahedron", "i", "in"},
81     {"VerticesOnGeometricVertices", "VertexOnGeometricVertex", "i", "iir"},
82     {"VerticesOnGeometricEdges", "VertexOnGeometricEdge", "i", "iirr"},
83     {"VerticesOnGeometricTriangles", "VertexOnGeometricTriangle", "i", "iirrr"},
84     {"VerticesOnGeometricQuadrilaterals", "VertexOnGeometricQuadrilateral", "i", "iirrr"},
85     {"EdgesOnGeometricEdges", "EdgeOnGeometricEdge", "i", "iir"},
86     {"Fault_FreeEdge", "Fault_FreeEdge", "i", "i"},
87     {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"},
88     {"Polygons", "Polygon", "", "iiiiiiiii"},
89     {"Fault_Overlap", "Fault_Overlap", "i", "i"},
90     {"Pyramids", "Pyramid", "i", "iiiiii"},
91     {"BoundingBox", "", "", "drdr"},
92     {"Body","i", "drdrdrdr"},
93     {"PrivateTable", "PrivateTable", "i", "i"},
94     {"Fault_BadShape", "Fault_BadShape", "i", "i"},
95     {"End", "", "", ""},
96     {"TrianglesOnGeometricTriangles", "TriangleOnGeometricTriangle", "i", "iir"},
97     {"TrianglesOnGeometricQuadrilaterals", "TriangleOnGeometricQuadrilateral", "i", "iir"},
98     {"QuadrilateralsOnGeometricTriangles", "QuadrilateralOnGeometricTriangle", "i", "iir"},
99     {"QuadrilateralsOnGeometricQuadrilaterals", "QuadrilateralOnGeometricQuadrilateral", "i", "iir"},
100     {"Tangents", "Tangent", "i", "dr"},
101     {"Normals", "Normal", "i", "dr"},
102     {"TangentAtVertices", "TangentAtVertex", "i", "ii"},
103     {"SolAtVertices", "SolAtVertex", "i", "sr"},
104     {"SolAtEdges", "SolAtEdge", "i", "sr"},
105     {"SolAtTriangles", "SolAtTriangle", "i", "sr"},
106     {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"},
107     {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"},
108     {"SolAtPrisms", "SolAtPrism", "i", "sr"},
109     {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"},
110     {"DSolAtVertices", "DSolAtVertex", "i", "sr"},
111     {"ISolAtVertices", "ISolAtVertex", "i", "i"},
112     {"ISolAtEdges", "ISolAtEdge", "i", "ii"},
113     {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"},
114     {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"},
115     {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"},
116     {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"},
117     {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"},
118     {"Iterations", "","","i"},
119     {"Time", "","","r"},
120     {"Fault_SmallTri", "Fault_SmallTri","i","i"},
121     {"CoarseHexahedra", "CoarseHexahedron", "i", "i"},
122     {"Fault_MultipleEdge", "Fault_MultipleEdge", "i", "i"}
123 };
124
125
126
127 MeshFormatParser::MeshFormatParser():GmfIniFlg(0)
128 {
129
130 }
131
132 /*----------------------------------------------------------*/
133 /* Open a mesh file in read or write mod                                        */
134 /*----------------------------------------------------------*/
135
136 int MeshFormatParser::GmfOpenMesh(const char *FilNam, int mod, ...)
137 {
138     int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0;
139     char str[ GmfStrSiz ];
140     va_list VarArg;
141     GmfMshSct *msh;
142     char *ptr;
143     int k;
144 #if defined(WIN32) && defined(UNICODE)
145     wchar_t* encoded = 0;
146     int size_needed = 0;
147 #endif
148     if(!GmfIniFlg)
149     {
150         for(i=0; i<=MaxMsh; i++)
151             //~GmfMshTab[i] = NULL;
152             GmfMshTab[i] = nullptr;
153
154         GmfIniFlg = 1;
155     }
156
157     /*---------------------*/
158     /* MESH STRUCTURE INIT */
159     /*---------------------*/
160
161     for(i=1; i<=MaxMsh; i++)
162         if(!GmfMshTab[i])
163         {
164             MshIdx = i;
165             break;
166         }
167
168
169     if( !MshIdx || !(msh = new GmfMshSct() ) )
170         return(0);
171
172     /* Copy the FilNam into the structure */
173
174     if(strlen(FilNam) + 7 >= GmfStrSiz)
175     {
176         //~free (msh);
177         delete msh;
178         return(0);
179     }
180
181     strcpy(msh->FilNam, FilNam);
182
183     /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */
184
185     msh->mod = mod;
186     msh->buf = (unsigned char *)msh->DblBuf;
187     msh->FltBuf = (float *)msh->DblBuf;
188     msh->IntBuf = (int *)msh->DblBuf;
189
190     k = static_cast<int>(strlen(msh->FilNam)) - 6;
191     if(k < 0)
192         k = 0;
193     ptr = msh->FilNam+k;
194     if(strstr(ptr, ".meshb"))
195         msh->typ |= (Bin | MshFil);
196     else if(strstr(ptr, ".mesh"))
197         msh->typ |= (Asc | MshFil);
198     else if(strstr(ptr, ".solb"))
199         msh->typ |= (Bin | SolFil);
200     else if(strstr(ptr, ".sol"))
201         msh->typ |= (Asc | SolFil);
202     else {
203         //~free (msh);
204         delete msh;
205         return(0);
206     }
207
208     /* Open the file in the required mod and initialise the mesh structure */
209
210     if(msh->mod == GmfRead)
211     {
212
213         /*-----------------------*/
214         /* OPEN FILE FOR READING */
215         /*-----------------------*/
216
217         va_start(VarArg, mod);
218         PtrVer = va_arg(VarArg, int *);
219         PtrDim = va_arg(VarArg, int *);
220         va_end(VarArg);
221
222         /* Create the name string and open the file */
223 #if defined(WIN32) && defined(UNICODE)
224         size_needed = MultiByteToWideChar(CP_UTF8, 0, msh->FilNam, strlen(msh->FilNam), NULL, 0);
225         //~encoded = malloc((size_needed + 1)*sizeof(wchar_t));
226         encoded = new wchar_t[size_needed + 1] ;
227         MultiByteToWideChar(CP_UTF8, 0, msh->FilNam, strlen(msh->FilNam), encoded, size_needed);
228         encoded[size_needed] = '\0';
229         if (!(msh->hdl = _wfopen(encoded, L"rb")))
230 #else
231         if (!(msh->hdl = fopen(msh->FilNam, "rb")))
232 #endif
233         {
234
235             delete msh;
236 #if defined(WIN32) && defined(UNICODE)
237
238             delete [] encoded;
239 #endif
240             return(0);
241         }
242
243 #if defined(WIN32) && defined(UNICODE)
244
245         delete [] encoded;
246 #endif
247
248         /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
249
250         if(msh->typ & Bin)
251         {
252             fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl);
253
254             if( (msh->cod != 1) && (msh->cod != 16777216) )
255             {
256
257                 delete msh;
258                 return(0);
259             }
260
261             ScaWrd(msh, (unsigned char *)&msh->ver);
262
263             if( (msh->ver < 1) || (msh->ver > 3) )
264             {
265
266                 delete msh;
267                 return(0);
268             }
269
270             if( (msh->ver == 3) && (sizeof(long) == 4) )
271             {
272
273                 delete msh;
274                 return(0);
275             }
276
277             ScaWrd(msh, (unsigned char *)&KwdCod);
278
279             if(KwdCod != GmfDimension)
280             {
281
282                 delete msh;
283                 return(0);
284             }
285
286             GetPos(msh);
287             ScaWrd(msh, (unsigned char *)&msh->dim);
288         }
289         else
290         {
291             do
292             {
293                 res = fscanf(msh->hdl, "%s", str);
294             } while( (res != EOF) && strcmp(str, "MeshVersionFormatted") );
295
296             if(res == EOF)
297             {
298
299                 delete msh;
300                 return(0);
301             }
302
303             fscanf(msh->hdl, "%d", &msh->ver);
304
305             if( (msh->ver < 1) || (msh->ver > 3) )
306             {
307
308                 delete msh;
309                 return(0);
310             }
311
312             do
313             {
314                 res = fscanf(msh->hdl, "%s", str);
315             } while( (res != EOF) && strcmp(str, "Dimension") );
316
317             if(res == EOF)
318             {
319
320                 delete msh;
321                 return(0);
322             }
323
324             fscanf(msh->hdl, "%d", &msh->dim);
325         }
326
327         if( (msh->dim != 2) && (msh->dim != 3) )
328         {
329
330             delete msh;
331             return(0);
332         }
333
334         (*PtrVer) = msh->ver;
335         (*PtrDim) = msh->dim;
336
337         /*------------*/
338         /* KW READING */
339         /*------------*/
340
341         /* Read the list of kw present in the file */
342
343         if(!ScaKwdTab(msh))
344         {
345
346             delete msh;
347             return(0);
348         }
349
350         GmfMshTab[ MshIdx ] = msh;
351
352         return(MshIdx);
353     }
354     else if(msh->mod == GmfWrite)
355     {
356
357         /*-----------------------*/
358         /* OPEN FILE FOR WRITING */
359         /*-----------------------*/
360
361         msh->cod = 1;
362
363         /* Check if the user provided a valid version number and dimension */
364
365         va_start(VarArg, mod);
366         msh->ver = va_arg(VarArg, int);
367         msh->dim = va_arg(VarArg, int);
368         va_end(VarArg);
369
370         if( (msh->ver < 1) || (msh->ver > 3) )
371         {
372
373             delete msh;
374             return(0);
375         }
376
377         if( (msh->ver == 3) && (sizeof(long) == 4) )
378         {
379
380             delete msh;
381             return(0);
382         }
383
384         if( (msh->dim != 2) && (msh->dim != 3) )
385         {
386
387             delete msh;
388             return(0);
389         }
390
391         /* Create the mesh file */
392 #if defined(WIN32) && defined(UNICODE)
393         size_needed = MultiByteToWideChar(CP_UTF8, 0, msh->FilNam, strlen(msh->FilNam), NULL, 0);
394
395         encoded = new wchar_t[size_needed + 1];
396         MultiByteToWideChar(CP_UTF8, 0, msh->FilNam, strlen(msh->FilNam), encoded, size_needed);
397         encoded[size_needed] = '\0';
398         if (!(msh->hdl = _wfopen(encoded, L"wb")))
399 #else
400         if(!(msh->hdl = fopen(msh->FilNam, "wb")))
401 #endif
402         {
403
404             delete msh;
405 #if defined(WIN32) && defined(UNICODE)
406
407             delete []encoded;
408 #endif
409             return(0);
410         }
411
412 #if defined(WIN32) && defined(UNICODE)
413
414         delete []encoded;
415 #endif
416         GmfMshTab[ MshIdx ] = msh;
417
418
419         /*------------*/
420         /* KW WRITING */
421         /*------------*/
422
423         /* Write the mesh version and dimension */
424
425         if(msh->typ & Asc)
426         {
427             fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver);
428             fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim);
429         }
430         else
431         {
432             RecWrd(msh, (unsigned char *)&msh->cod);
433             RecWrd(msh, (unsigned char *)&msh->ver);
434             GmfSetKwd(MshIdx, GmfDimension, 0);
435             RecWrd(msh, (unsigned char *)&msh->dim);
436         }
437
438         return(MshIdx);
439     }
440     else
441     {
442
443         delete msh;
444         return(0);
445     }
446 }
447
448
449 /*----------------------------------------------------------*/
450 /* Close a meshfile in the right way                                            */
451 /*----------------------------------------------------------*/
452
453 int MeshFormatParser::GmfCloseMesh(int MshIdx)
454 {
455     int res = 1;
456     GmfMshSct *msh;
457
458     if( (MshIdx < 1) || (MshIdx > MaxMsh) )
459         return(0);
460
461     msh = GmfMshTab[ MshIdx ];
462     RecBlk(msh, msh->buf, 0);
463
464     /* In write down the "End" kw in write mode */
465
466     if(msh->mod == GmfWrite) {
467         if(msh->typ & Asc)
468             fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]);
469         else
470             GmfSetKwd(MshIdx, GmfEnd, 0);
471     }
472     /* Close the file and free the mesh structure */
473
474     if(fclose(msh->hdl))
475         res = 0;
476
477
478     delete msh;
479
480     GmfMshTab[ MshIdx ] = nullptr;
481
482     return(res);
483 }
484
485
486 /*----------------------------------------------------------*/
487 /* Read the number of lines and set the position to this kwd*/
488 /*----------------------------------------------------------*/
489
490 int MeshFormatParser::GmfStatKwd(int MshIdx, int KwdCod, ...)
491 {
492     int i, *PtrNmbTyp, *PtrSolSiz, *TypTab;
493     GmfMshSct *msh;
494     KwdSct *kwd;
495     va_list VarArg;
496
497     if( (MshIdx < 1) || (MshIdx > MaxMsh) )
498         return(0);
499
500     msh = GmfMshTab[ MshIdx ];
501
502     if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
503         return(0);
504
505     kwd = &msh->KwdTab[ KwdCod ];
506
507     if(!kwd->NmbLin)
508         return(0);
509
510     /* Read further arguments if this kw is a sol */
511
512     if(kwd->typ == SolKwd)
513     {
514         va_start(VarArg, KwdCod);
515
516         PtrNmbTyp = va_arg(VarArg, int *);
517         *PtrNmbTyp = kwd->NmbTyp;
518
519         PtrSolSiz = va_arg(VarArg, int *);
520         *PtrSolSiz = kwd->SolSiz;
521
522         TypTab = va_arg(VarArg, int *);
523
524         for(i=0; i<kwd->NmbTyp; i++)
525             TypTab[i] = kwd->TypTab[i];
526
527         va_end(VarArg);
528     }
529
530     return(kwd->NmbLin);
531 }
532
533
534 /*----------------------------------------------------------*/
535 /* Set the current file position to a given kwd                         */
536 /*----------------------------------------------------------*/
537
538 int MeshFormatParser::GmfGotoKwd(int MshIdx, int KwdCod)
539 {
540     GmfMshSct *msh;
541     KwdSct *kwd;
542
543     if( (MshIdx < 1) || (MshIdx > MaxMsh) )
544         return(0);
545
546     msh = GmfMshTab[ MshIdx ];
547
548     if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
549         return(0);
550
551     kwd = &msh->KwdTab[ KwdCod ];
552
553     if(!kwd->NmbLin)
554         return(0);
555
556     return(fseek(msh->hdl, kwd->pos, SEEK_SET));
557 }
558
559
560 /*----------------------------------------------------------*/
561 /* Write the kwd and set the number of lines                            */
562 /*----------------------------------------------------------*/
563
564 int MeshFormatParser::GmfSetKwd(int MshIdx, int KwdCod, ...)
565 {
566     int i, NmbLin=0, *TypTab;
567     long CurPos;
568     va_list VarArg;
569     GmfMshSct *msh;
570     KwdSct *kwd;
571
572     if( (MshIdx < 1) || (MshIdx > MaxMsh) )
573         return(0);
574
575     msh = GmfMshTab[ MshIdx ];
576     RecBlk(msh, msh->buf, 0);
577
578     if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
579         return(0);
580
581     kwd = &msh->KwdTab[ KwdCod ];
582
583     /* Read further arguments if this kw has a header */
584
585     if(strlen(GmfKwdFmt[ KwdCod ][2]))
586     {
587         va_start(VarArg, KwdCod);
588         NmbLin = va_arg(VarArg, int);
589
590         if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr"))
591         {
592             kwd->NmbTyp = va_arg(VarArg, int);
593             TypTab = va_arg(VarArg, int *);
594
595             for(i=0; i<kwd->NmbTyp; i++)
596                 kwd->TypTab[i] = TypTab[i];
597         }
598
599         va_end(VarArg);
600     }
601
602     /* Setup the kwd info */
603
604     ExpFmt(msh, KwdCod);
605
606     if(!kwd->typ)
607         return(0);
608     else if(kwd->typ == InfKwd)
609         kwd->NmbLin = 1;
610     else
611         kwd->NmbLin = NmbLin;
612
613     /* Store the next kwd position in binary file */
614
615     if( (msh->typ & Bin) && msh->NexKwdPos )
616     {
617         CurPos = ftell(msh->hdl);
618         fseek(msh->hdl, msh->NexKwdPos, SEEK_SET);
619         SetPos(msh, CurPos);
620         fseek(msh->hdl, CurPos, SEEK_SET);
621     }
622
623     /* Write the header */
624
625     if(msh->typ & Asc)
626     {
627         fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]);
628
629         if(kwd->typ != InfKwd)
630             fprintf(msh->hdl, "%d\n", kwd->NmbLin);
631
632         /* In case of solution field, write the extended header */
633
634         if(kwd->typ == SolKwd)
635         {
636             fprintf(msh->hdl, "%d ", kwd->NmbTyp);
637
638             for(i=0; i<kwd->NmbTyp; i++)
639                 fprintf(msh->hdl, "%d ", kwd->TypTab[i]);
640
641             fprintf(msh->hdl, "\n\n");
642         }
643     }
644     else
645     {
646         RecWrd(msh, (unsigned char *)&KwdCod);
647         msh->NexKwdPos = ftell(msh->hdl);
648         SetPos(msh, 0);
649
650         if(kwd->typ != InfKwd)
651             RecWrd(msh, (unsigned char *)&kwd->NmbLin);
652
653         /* In case of solution field, write the extended header at once */
654
655         if(kwd->typ == SolKwd)
656         {
657             RecWrd(msh, (unsigned char *)&kwd->NmbTyp);
658
659             for(i=0; i<kwd->NmbTyp; i++)
660                 RecWrd(msh, (unsigned char *)&kwd->TypTab[i]);
661         }
662     }
663
664     /* Reset write buffer position */
665     msh->pos = 0;
666
667     /* Estimate the total file size and check whether it crosses the 2GB threshold */
668
669     msh->siz += kwd->NmbLin * kwd->NmbWrd * WrdSiz;
670
671     if(msh->siz > static_cast<long>(2E9))
672         return(0);
673     else
674         return(kwd->NmbLin);
675 }
676
677
678 /*----------------------------------------------------------*/
679 /* Read a full line from the current kwd                                        */
680 /*----------------------------------------------------------*/
681
682 void MeshFormatParser::GmfGetLin(int MshIdx, int KwdCod, ...)
683 {
684     int i, j;
685     float *FltSolTab;
686     double *DblSolTab;
687     va_list VarArg;
688     GmfMshSct *msh = GmfMshTab[ MshIdx ];
689     KwdSct *kwd = &msh->KwdTab[ KwdCod ];
690
691     /* Start decoding the arguments */
692
693     va_start(VarArg, KwdCod);
694
695     if(kwd->typ != SolKwd)
696     {
697         int k, nb_repeat = 0;
698
699         if(msh->ver == 1)
700         {
701             if(msh->typ & Asc)
702             {
703                 for(i=0; i<kwd->SolSiz; i++)
704                     if(kwd->fmt[i] == 'r')
705                         fscanf(msh->hdl, "%f", va_arg(VarArg, float *));
706                     else if(kwd->fmt[i] == 'n') {
707                         fscanf(msh->hdl, "%d", &nb_repeat);
708                         *(va_arg(VarArg,  int *)) = nb_repeat;
709                         for(k=0; k<nb_repeat; k++)
710                             fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
711                     }
712                     else
713                         fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
714             }
715             else
716             {
717                 for(i=0; i<kwd->SolSiz; i++)
718                     if(kwd->fmt[i] == 'r')
719                         ScaWrd(msh, (unsigned char *)va_arg(VarArg, float *));
720                     else if(kwd->fmt[i] == 'n') {
721                         ScaWrd(msh, (unsigned char *)&nb_repeat);
722                         *(va_arg(VarArg,  int *)) = nb_repeat;
723                         for(k=0; k<nb_repeat; k++)
724                             ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
725                     }
726                     else
727                         ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
728             }
729         }
730         else
731         {
732             if(msh->typ & Asc)
733             {
734                 for(i=0; i<kwd->SolSiz; i++)
735                     if(kwd->fmt[i] == 'r')
736                         fscanf(msh->hdl, "%lf", va_arg(VarArg, double *));
737                     else if(kwd->fmt[i] == 'n') {
738                         fscanf(msh->hdl, "%d", &nb_repeat);
739                         *(va_arg(VarArg,  int *)) = nb_repeat;
740                         for(k=0; k<nb_repeat; k++)
741                             fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
742                     }
743                     else
744                         fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
745             }
746             else
747                 for(i=0; i<kwd->SolSiz; i++)
748                     if(kwd->fmt[i] == 'r')
749                         ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *));
750                     else if(kwd->fmt[i] == 'n') {
751                         ScaWrd(msh, (unsigned char *)&nb_repeat);
752                         *(va_arg(VarArg,  int *)) = nb_repeat;
753                         for(k=0; k<nb_repeat; k++)
754                             ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
755                     }
756                     else
757                         ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
758         }
759     }
760     else
761     {
762         if(msh->ver == 1)
763         {
764             FltSolTab = va_arg(VarArg, float *);
765
766             if(msh->typ & Asc)
767                 for(j=0; j<kwd->SolSiz; j++)
768                     fscanf(msh->hdl, "%f", &FltSolTab[j]);
769             else
770                 ScaBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
771         }
772         else
773         {
774             DblSolTab = va_arg(VarArg, double *);
775
776             if(msh->typ & Asc)
777                 for(j=0; j<kwd->SolSiz; j++)
778                     fscanf(msh->hdl, "%lf", &DblSolTab[j]);
779             else
780                 for(j=0; j<kwd->SolSiz; j++)
781                     ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]);
782         }
783     }
784
785     va_end(VarArg);
786 }
787
788
789 /*----------------------------------------------------------*/
790 /* Write a full line from the current kwd                                       */
791 /*----------------------------------------------------------*/
792
793 void MeshFormatParser::GmfSetLin(int MshIdx, int KwdCod, ...)
794 {
795     int i, j, pos, *IntBuf;
796     float *FltSolTab;
797     double *DblSolTab, *DblBuf;
798     va_list VarArg;
799     GmfMshSct *msh = GmfMshTab[ MshIdx ];
800     KwdSct *kwd = &msh->KwdTab[ KwdCod ];
801
802     /* Start decoding the arguments */
803
804     va_start(VarArg, KwdCod);
805
806     if(kwd->typ != SolKwd)
807     {
808         int k, nb_repeat = 0;
809
810         if(msh->ver == 1)
811         {
812             if(msh->typ & Asc)
813             {
814                 for(i=0; i<kwd->SolSiz; i++)
815                     if(kwd->fmt[i] == 'r')
816                         fprintf(msh->hdl, "%g ", (float)va_arg(VarArg, double));
817                     else if(kwd->fmt[i] == 'n') {
818                         nb_repeat = va_arg(VarArg, int);
819                         fprintf(msh->hdl, "%d ", nb_repeat);
820                         for(k=0; k<nb_repeat; k++)
821                             fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
822                     }
823                     else
824                         fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
825             }
826             else
827             {
828                 int size_of_block = kwd->SolSiz;
829                 for(i=0; i<kwd->SolSiz; i++)
830                     if(kwd->fmt[i] == 'r')
831                         msh->FltBuf[i] = static_cast<float>(va_arg(VarArg, double));
832                     else if(kwd->fmt[i] == 'n') {
833                         nb_repeat = va_arg(VarArg, int);
834                         msh->FltBuf[i] = static_cast<float> (nb_repeat);
835                         for(k=0; k<nb_repeat; k++) {
836                             msh->IntBuf[i+1+k] = va_arg(VarArg, int);
837                             size_of_block ++;
838                         }
839                     }
840                     else
841                         msh->IntBuf[i] = va_arg(VarArg, int);
842
843                 RecBlk(msh, msh->buf, size_of_block);
844             }
845         }
846         else
847         {
848             if(msh->typ & Asc)
849             {
850                 for(i=0; i<kwd->SolSiz; i++)
851                     if(kwd->fmt[i] == 'r')
852                         fprintf(msh->hdl, "%.15lg ", va_arg(VarArg, double));
853                     else if(kwd->fmt[i] == 'n') {
854                         nb_repeat = va_arg(VarArg, int);
855                         fprintf(msh->hdl, "%d ", nb_repeat);
856                         for(k=0; k<nb_repeat; k++)
857                             fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
858                     }
859                     else
860                         fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
861             }
862             else
863             {
864                 pos = 0;
865
866                 for(i=0; i<kwd->SolSiz; i++)
867                     if(kwd->fmt[i] == 'r')
868                     {
869                         DblBuf = (double *)&msh->buf[ pos ];
870                         *DblBuf = va_arg(VarArg, double);
871                         pos += 8;
872                     }
873                     else if(kwd->fmt[i] == 'n')
874                     {
875                         IntBuf = (int *)&msh->buf[ pos ];
876                         nb_repeat = va_arg(VarArg, int);
877                         *IntBuf = nb_repeat;
878                         pos += 4;
879                         for(k=0; k<nb_repeat; k++) {
880                             IntBuf = (int *)&msh->buf[ pos ];
881                             *IntBuf = va_arg(VarArg, int);
882                             pos += 4;
883                         }
884                     }
885                     else
886                     {
887                         IntBuf = (int *)&msh->buf[ pos ];
888                         *IntBuf = va_arg(VarArg, int);
889                         pos += 4;
890                     }
891                 RecBlk(msh, msh->buf, pos/4);
892             }
893         }
894     }
895     else
896     {
897         if(msh->ver == 1)
898         {
899             FltSolTab = va_arg(VarArg, float *);
900
901             if(msh->typ & Asc)
902                 for(j=0; j<kwd->SolSiz; j++)
903                     fprintf(msh->hdl, "%g ", FltSolTab[j]);
904             else
905                 RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
906         }
907         else
908         {
909             DblSolTab = va_arg(VarArg, double *);
910
911             if(msh->typ & Asc)
912                 for(j=0; j<kwd->SolSiz; j++)
913                     fprintf(msh->hdl, "%.15lg ", DblSolTab[j]);
914             else
915                 RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd);
916         }
917     }
918
919     va_end(VarArg);
920
921     if(msh->typ & Asc)
922         fprintf(msh->hdl, "\n");
923 }
924
925
926 /*----------------------------------------------------------*/
927 /* Private procedure for transmesh : copy a whole line          */
928 /*----------------------------------------------------------*/
929
930 void MeshFormatParser::GmfCpyLin(int InpIdx, int OutIdx, int KwdCod)
931 {
932     double d;
933     float f;
934     int i, a;
935     GmfMshSct *InpMsh = GmfMshTab[ InpIdx ], *OutMsh = GmfMshTab[ OutIdx ];
936     KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ];
937
938     for(i=0; i<kwd->SolSiz; i++)
939     {
940         if(kwd->fmt[i] == 'r')
941         {
942             if(InpMsh->ver == 1)
943             {
944                 if(InpMsh->typ & Asc)
945                     fscanf(InpMsh->hdl, "%f", &f);
946                 else
947                     ScaWrd(InpMsh, (unsigned char *)&f);
948
949                 d = f;
950             }
951             else
952             {
953                 if(InpMsh->typ & Asc)
954                     fscanf(InpMsh->hdl, "%lf", &d);
955                 else
956                     ScaDblWrd(InpMsh, (unsigned char *)&d);
957
958                 f = (float)d;
959             }
960
961             if(OutMsh->ver == 1)
962                 if(OutMsh->typ & Asc)
963                     fprintf(OutMsh->hdl, "%g ", f);
964                 else
965                     RecWrd(OutMsh, (unsigned char *)&f);
966             else if(OutMsh->typ & Asc)
967                 fprintf(OutMsh->hdl, "%.15g ", d);
968             else
969                 RecDblWrd(OutMsh, (unsigned char *)&d);
970         }
971         else if(kwd->fmt[i] == 'n')
972         {
973             int k, nb_repeat = 0;
974
975             if(InpMsh->typ & Asc)
976                 fscanf(InpMsh->hdl, "%d", &a);
977             else
978                 ScaWrd(InpMsh, (unsigned char *)&a);
979
980             nb_repeat = a;
981
982             if(OutMsh->typ & Asc)
983                 fprintf(OutMsh->hdl, "%d ", a);
984             else
985                 RecWrd(OutMsh, (unsigned char *)&a);
986
987             for(k=0; k<nb_repeat; k++) {
988                 if(InpMsh->typ & Asc)
989                     fscanf(InpMsh->hdl, "%d", &a);
990                 else
991                     ScaWrd(InpMsh, (unsigned char *)&a);
992
993                 if(OutMsh->typ & Asc)
994                     fprintf(OutMsh->hdl, "%d ", a);
995                 else
996                     RecWrd(OutMsh, (unsigned char *)&a);
997             }
998         }
999         else
1000         {
1001             if(InpMsh->typ & Asc)
1002                 fscanf(InpMsh->hdl, "%d", &a);
1003             else
1004                 ScaWrd(InpMsh, (unsigned char *)&a);
1005
1006             if(OutMsh->typ & Asc)
1007                 fprintf(OutMsh->hdl, "%d ", a);
1008             else
1009                 RecWrd(OutMsh, (unsigned char *)&a);
1010         }
1011     }
1012
1013     if(OutMsh->typ & Asc)
1014         fprintf(OutMsh->hdl, "\n");
1015 }
1016
1017
1018 /*----------------------------------------------------------*/
1019 /* Find every kw present in a meshfile                                          */
1020 /*----------------------------------------------------------*/
1021
1022 int MeshFormatParser::ScaKwdTab(GmfMshSct *msh)
1023 {
1024     int KwdCod;
1025     long  NexPos, CurPos, EndPos;
1026     char str[ GmfStrSiz ];
1027
1028     if(msh->typ & Asc)
1029     {
1030         /* Scan each string in the file until the end */
1031
1032         while(fscanf(msh->hdl, "%s", str) != EOF)
1033         {
1034             /* Fast test in order to reject quickly the numeric values */
1035
1036             if(isalpha(str[0]))
1037             {
1038                 /* Search which kwd code this string is associated with,
1039                         then get its header and save the current position in file (just before the data) */
1040                 // printf("libmesh ScaKwdTab %s\n", str);
1041                 for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++)
1042                     if(!strcmp(str, GmfKwdFmt[ KwdCod ][0]))
1043                     {
1044                         ScaKwdHdr(msh, KwdCod);
1045                         break;
1046                     }
1047             }
1048             else if(str[0] == '#')
1049                 while(fgetc(msh->hdl) != '\n');
1050         }
1051     }
1052     else
1053     {
1054         /* Get file size */
1055
1056         CurPos = ftell(msh->hdl);
1057         fseek(msh->hdl, 0, SEEK_END);
1058         EndPos = ftell(msh->hdl);
1059         fseek(msh->hdl, CurPos, SEEK_SET);
1060
1061         /* Jump through kwd positions in the file */
1062
1063         do
1064         {
1065             /* Get the kwd code and the next kwd position */
1066
1067             ScaWrd(msh, (unsigned char *)&KwdCod);
1068             NexPos = GetPos(msh);
1069
1070             if(NexPos > EndPos)
1071                 return(0);
1072
1073             /* Check if this kwd belongs to this mesh version */
1074
1075             if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) )
1076                 ScaKwdHdr(msh, KwdCod);
1077
1078             /* Go to the next kwd */
1079
1080             if(NexPos)
1081                 fseek(msh->hdl, NexPos, SEEK_SET);
1082         } while(NexPos && (KwdCod != GmfEnd));
1083     }
1084
1085     return(1);
1086 }
1087
1088
1089 /*----------------------------------------------------------*/
1090 /* Read and setup the keyword's header                                          */
1091 /*----------------------------------------------------------*/
1092
1093 void MeshFormatParser::ScaKwdHdr(GmfMshSct *msh, int KwdCod)
1094 {
1095     int i;
1096     KwdSct *kwd = &msh->KwdTab[ KwdCod ];
1097
1098     if(!strcmp("i", GmfKwdFmt[ KwdCod ][2]))
1099     {
1100         if(msh->typ & Asc)
1101             fscanf(msh->hdl, "%d", &kwd->NmbLin);
1102         else
1103             ScaWrd(msh, (unsigned char *)&kwd->NmbLin);
1104     }
1105     else
1106         kwd->NmbLin = 1;
1107
1108     if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3]))
1109     {
1110         if(msh->typ & Asc)
1111         {
1112             fscanf(msh->hdl, "%d", &kwd->NmbTyp);
1113
1114             for(i=0; i<kwd->NmbTyp; i++)
1115                 fscanf(msh->hdl, "%d", &kwd->TypTab[i]);
1116         }
1117         else
1118         {
1119             ScaWrd(msh, (unsigned char *)&kwd->NmbTyp);
1120
1121             for(i=0; i<kwd->NmbTyp; i++)
1122                 ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]);
1123         }
1124     }
1125
1126     ExpFmt(msh, KwdCod);
1127     kwd->pos = ftell(msh->hdl);
1128 }
1129
1130
1131 /*----------------------------------------------------------*/
1132 /* Expand the compacted format and compute the line size        */
1133 /*----------------------------------------------------------*/
1134
1135 void MeshFormatParser::ExpFmt(GmfMshSct *msh, int KwdCod)
1136 {
1137     int i, j, TmpSiz=0;
1138     char chr;
1139     const char *InpFmt = GmfKwdFmt[ KwdCod ][3];
1140     KwdSct *kwd = &msh->KwdTab[ KwdCod ];
1141
1142     /* Set the kwd's type */
1143
1144     if(!strlen(GmfKwdFmt[ KwdCod ][2]))
1145         kwd->typ = InfKwd;
1146     else if(!strcmp(InpFmt, "sr"))
1147         kwd->typ = SolKwd;
1148     else
1149         kwd->typ = RegKwd;
1150
1151     /* Get the solution-field's size */
1152
1153     if(kwd->typ == SolKwd)
1154         for(i=0; i<kwd->NmbTyp; i++)
1155             switch(kwd->TypTab[i])
1156             {
1157             case GmfSca    :
1158                 TmpSiz += 1;
1159                 break;
1160             case GmfVec    :
1161                 TmpSiz += msh->dim;
1162                 break;
1163             case GmfSymMat :
1164                 TmpSiz += (msh->dim * (msh->dim+1)) / 2;
1165                 break;
1166             case GmfMat    :
1167                 TmpSiz += msh->dim * msh->dim;
1168                 break;
1169             }
1170
1171     /* Scan each character from the format string */
1172
1173     i = kwd->SolSiz = kwd->NmbWrd = 0;
1174
1175     while(i < static_cast<int>(strlen(InpFmt)) )
1176     {
1177         chr = InpFmt[ i++ ];
1178
1179         if(chr == 'd')
1180         {
1181             chr = InpFmt[i++];
1182
1183             for(j=0; j<msh->dim; j++)
1184                 kwd->fmt[ kwd->SolSiz++ ] = chr;
1185         }
1186         else if(chr == 's')
1187         {
1188             chr = InpFmt[i++];
1189
1190             for(j=0; j<TmpSiz; j++)
1191                 kwd->fmt[ kwd->SolSiz++ ] = chr;
1192         }
1193         else
1194             kwd->fmt[ kwd->SolSiz++ ] = chr;
1195     }
1196
1197     for(i=0; i<kwd->SolSiz; i++)
1198         if(kwd->fmt[i] == 'i')
1199             kwd->NmbWrd++;
1200         else if(msh->ver >= 2)
1201             kwd->NmbWrd += 2;
1202         else
1203             kwd->NmbWrd++;
1204 }
1205
1206
1207 /*----------------------------------------------------------*/
1208 /* Read a four bytes word from a mesh file                                      */
1209 /*----------------------------------------------------------*/
1210
1211 void MeshFormatParser::ScaWrd(GmfMshSct *msh, unsigned char *wrd)
1212 {
1213     unsigned char swp;
1214
1215     fread(wrd, WrdSiz, 1, msh->hdl);
1216
1217     if(msh->cod == 1)
1218         return;
1219
1220     swp = wrd[3];
1221     wrd[3] = wrd[0];
1222     wrd[0] = swp;
1223
1224     swp = wrd[2];
1225     wrd[2] = wrd[1];
1226     wrd[1] = swp;
1227 }
1228
1229
1230 /*----------------------------------------------------------*/
1231 /* Read an eight bytes word from a mesh file                            */
1232 /*----------------------------------------------------------*/
1233
1234 void MeshFormatParser::ScaDblWrd(GmfMshSct *msh, unsigned char *wrd)
1235 {
1236     int i;
1237     unsigned char swp;
1238
1239     fread(wrd, WrdSiz, 2, msh->hdl);
1240
1241     if(msh->cod == 1)
1242         return;
1243
1244     for(i=0; i<4; i++)
1245     {
1246         swp = wrd[7-i];
1247         wrd[7-i] = wrd[i];
1248         wrd[i] = swp;
1249     }
1250 }
1251
1252
1253 /*----------------------------------------------------------*/
1254 /* Read ablock of four bytes word from a mesh file                      */
1255 /*----------------------------------------------------------*/
1256
1257 void MeshFormatParser::ScaBlk(GmfMshSct *msh, unsigned char *blk, int siz)
1258 {
1259     int i, j;
1260     unsigned char swp, *wrd;
1261
1262     fread(blk, WrdSiz, siz, msh->hdl);
1263
1264     if(msh->cod == 1)
1265         return;
1266
1267     for(i=0; i<siz; i++)
1268     {
1269         wrd = &blk[ i * 4 ];
1270
1271         for(j=0; j<2; j++)
1272         {
1273             swp = wrd[ 3-j ];
1274             wrd[ 3-j ] = wrd[j];
1275             wrd[j] = swp;
1276         }
1277     }
1278 }
1279
1280
1281 /*----------------------------------------------------------*/
1282 /* Read a 4 or 8 bytes position in mesh file                            */
1283 /*----------------------------------------------------------*/
1284
1285 long MeshFormatParser::GetPos(GmfMshSct *msh)
1286 {
1287     int IntVal;
1288     long pos;
1289
1290     if(msh->ver >= 3)
1291         ScaDblWrd(msh, (unsigned char*)&pos);
1292     else
1293     {
1294         ScaWrd(msh, (unsigned char*)&IntVal);
1295         pos = IntVal;
1296     }
1297
1298     return(pos);
1299 }
1300
1301
1302 /*----------------------------------------------------------*/
1303 /* Write a four bytes word to a mesh file                                       */
1304 /*----------------------------------------------------------*/
1305
1306 void MeshFormatParser::RecWrd(GmfMshSct *msh, unsigned char *wrd)
1307 {
1308     fwrite(wrd, WrdSiz, 1, msh->hdl);
1309 }
1310
1311
1312 /*----------------------------------------------------------*/
1313 /* Write an eight bytes word to a mesh file                                     */
1314 /*----------------------------------------------------------*/
1315
1316 void MeshFormatParser::RecDblWrd(GmfMshSct *msh, unsigned char *wrd)
1317 {
1318     fwrite(wrd, WrdSiz, 2, msh->hdl);
1319 }
1320
1321
1322 /*----------------------------------------------------------*/
1323 /* Write a block of four bytes word to a mesh file                      */
1324 /*----------------------------------------------------------*/
1325
1326 void MeshFormatParser::RecBlk(GmfMshSct *msh, unsigned char *blk, int siz)
1327 {
1328     /* Copy this line-block into the main mesh buffer */
1329
1330     if(siz)
1331     {
1332         memcpy(&msh->blk[ msh->pos ], blk, siz * WrdSiz);
1333         msh->pos += siz * WrdSiz;
1334     }
1335
1336     /* When the buffer is full or this procedure is called with a 0 size, flush the cache on disk */
1337
1338     if( (msh->pos > BufSiz) || (!siz && msh->pos) )
1339     {
1340         fwrite(msh->blk, 1, msh->pos, msh->hdl);
1341         msh->pos = 0;
1342     }
1343 }
1344
1345
1346 /*----------------------------------------------------------*/
1347 /* Write a 4 or 8 bytes position in a mesh file                         */
1348 /*----------------------------------------------------------*/
1349
1350 void MeshFormatParser::SetPos(GmfMshSct *msh, long pos)
1351 {
1352     int IntVal;
1353
1354     if(msh->ver >= 3)
1355         RecDblWrd(msh, (unsigned char*)&pos);
1356     else
1357     {
1358         IntVal = static_cast<int>(pos);
1359         RecWrd(msh, (unsigned char*)&IntVal);
1360     }
1361 }