Salome HOME
Update copyrights
[tools/medcoupling.git] / src / MEDLoader / MEDLoaderBase.cxx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDLoaderBase.hxx"
22 #include "InterpKernelException.hxx"
23
24 #include <sstream>
25 #include <fstream>
26 #include <cstring>
27 #include <iostream>
28
29 const char MEDLoaderBase::WHITE_SPACES[]=" \n";
30
31 int MEDLoaderBase::getStatusOfFile(const std::string& fileName)
32 {
33   std::ifstream ifs;
34   ifs.open(fileName.c_str());
35   if((ifs.rdstate() & std::ifstream::failbit)!=0)
36     {
37       ifs.close();
38       return NOT_EXIST;
39     }
40   std::ofstream ofs(fileName.c_str(),std::ios_base::app);
41   if((ofs.rdstate() & std::ofstream::failbit)!=0)
42     {
43       return EXIST_RDONLY;
44     }
45   return EXIST_RW;
46 }
47
48 char *MEDLoaderBase::buildEmptyString(int lgth)
49 {
50   char *ret=new char[lgth+1];
51   std::fill(ret,ret+lgth,' ');
52   ret[lgth]='\0';
53   return ret;
54 }
55
56 void MEDLoaderBase::getDirAndBaseName(const std::string& fullName, std::string& dirName, std::string& baseName)
57 {
58   std::size_t pos=fullName.find_last_of(getPathSep());
59   if(pos!=std::string::npos)
60     {
61       dirName=fullName.substr(0,pos);
62       baseName=fullName.substr(pos+1);
63     }
64   else
65     {
66       dirName.clear();
67       baseName=fullName;
68     }
69 }
70
71 std::string MEDLoaderBase::joinPath(const std::string& dirName, const std::string& baseName)
72 {
73   if(!dirName.empty())
74     return dirName+getPathSep()+baseName;
75   else
76     return baseName;
77 }
78
79 std::string MEDLoaderBase::getPathSep()
80 {
81 #ifndef WIN32
82   return std::string("/");
83 #else
84   return std::string("\\");
85 #endif
86 }
87
88 std::string MEDLoaderBase::buildUnionUnit(const char *name, int nameLgth, const char *unit, int unitLgth)
89 {
90   std::string ret(buildStringFromFortran(name,nameLgth));
91   std::string unitCpp(buildStringFromFortran(unit,unitLgth));
92   if(unitCpp.empty() || unitCpp[0]=='\0')
93     return ret;
94   ret+=" [";
95   ret+=unitCpp;
96   ret+="]";
97   return ret;
98 }
99
100 void MEDLoaderBase::splitIntoNameAndUnit(const std::string& s, std::string& name, std::string& unit)
101 {
102   std::string::size_type f1=s.find_first_of('[');
103   std::string::size_type f2=s.find_last_of(']');
104   if(f1!=std::string::npos && f2!=std::string::npos)
105     {
106       if(f1<f2)
107         {
108           name=s.substr(0,f1);
109           unit=s.substr(f1+1,f2-f1-1);
110           strip(name);
111           strip(unit);
112           return;
113         }
114     }
115   name=s;
116   unit="";
117 }
118
119 void MEDLoaderBase::strip(std::string& s)
120 {
121   std::string::size_type f1=s.find_first_not_of(' ');
122   if(f1==std::string::npos)
123     {
124       s="";
125       return ;
126     }
127   std::string::size_type f2=s.find_last_not_of(' ');
128   s=s.substr(f1,f2-f1+1);
129 }
130
131 /*!
132  * This method operates a safe copy from 'src' to 'dest' by checking the size of 'src' before trying to copy.
133  * If size of 'src' string is higher than 'maxLgth' the behaviour is dependent from 'behaviour' parameter.
134  * If 'behaviour' equals 0 an exception is thrown. If 'behaviour' equals 1 an attempt of zipping of string will be done
135  * ( see zipString to have more details).
136  */
137 void MEDLoaderBase::safeStrCpy(const char *src, int maxLgth, char *dest, int behaviour)
138 {
139   if((int)strlen(src)>maxLgth)
140     {
141       if(behaviour==0 || behaviour>1)
142         {
143           std::ostringstream oss; oss << "A string : \"" << src << "\" has been detected to be too long for MED File ( > " << maxLgth << ") !";
144           throw INTERP_KERNEL::Exception(oss.str().c_str());
145         }
146       else if(behaviour==1)
147         {
148           std::string s=zipString(src,maxLgth);
149           std::cerr << "A string : \"" << src << "\" has been detected to be too long for MED File ( > " << maxLgth << ") : ";
150           std::cerr << "zipping to : " << s << "\n";
151           strcpy(dest,s.c_str());
152           return ;
153         }
154     }
155   strcpy(dest,src);
156 }
157
158 /*!
159  * This method is equivalent to MEDLoaderBase::safeStrCpy except that here no '\0' car is put.
160  * This method should be used for multi string in one string.
161  */
162 void MEDLoaderBase::safeStrCpy2(const char *src, int maxLgth, char *dest, int behaviour)
163 {
164   if((int)strlen(src)>maxLgth)
165     {
166       if(behaviour==0 || behaviour>1)
167         {
168           std::ostringstream oss; oss << "A string : \"" << src << "\" has been detected to be too long for MED File ( > " << maxLgth << ") !";
169           throw INTERP_KERNEL::Exception(oss.str().c_str());
170         }
171       else if(behaviour==1)
172         {
173           std::string s=zipString(src,maxLgth);
174           std::cerr << "A string : \"" << src << "\" has been detected to be too long for MED File ( > " << maxLgth << ") : ";
175           std::cerr << "zipping to : " << s << "\n";
176           strcpy(dest,s.c_str());
177           return ;
178         }
179     }
180   int n(strlen(src));
181   std::fill(dest,dest+maxLgth,' ');
182   strncpy(dest,src,n);
183 }
184
185 std::string MEDLoaderBase::buildStringFromFortran(const char *expr, int lgth)
186 {
187   std::string ret(expr,lgth);
188   std::string whiteSpaces(WHITE_SPACES);
189   std::size_t lgthReal=strlen(ret.c_str());
190   std::string ret2=ret.substr(0,lgthReal);
191   std::size_t found=ret2.find_last_not_of(whiteSpaces);
192   if (found!=std::string::npos)
193     ret2.erase(found+1);
194   else
195     ret2.clear();//ret is all whitespace
196   return ret2;
197 }
198
199 /*!
200  * This method given the target size to respect 'sizeToRespect' tries to reduce size of 'src' string.
201  * This method uses several soft methods to do its job. But if it fails a simple cut of string will be performed.
202  */
203 std::string MEDLoaderBase::zipString(const std::string& src, int sizeToRespect)
204 {
205   std::string s(src);
206   strip(s);
207   if((int)s.length()<=sizeToRespect)
208     return s;
209   s=src;
210   zipEqualConsChar(s,3);
211   if((int)s.length()<=sizeToRespect)
212     return s;
213   s=src;
214   zipEqualConsChar(s,2);
215   if((int)s.length()<=sizeToRespect)
216     return s;
217   s=src;
218   return s.substr(0,sizeToRespect);
219 }
220
221 /*!
222  * This method see if there is in 's' more than 'minConsSmChar' consecutive same character.
223  * If yes, the group will be zipped using only one character for this group.
224  * If no such group is found, s remains unchanged.
225  */
226 void MEDLoaderBase::zipEqualConsChar(std::string& s, int minConsSmChar)
227 {
228   for(std::string::iterator it=s.begin();it!=s.end();it++)
229     {
230       char tmp=*it;
231       int sz=1;
232       for(std::string::iterator it2=it+1;it2!=s.end() && *it2==tmp;it2++)
233         sz++;
234       if(sz>=minConsSmChar)
235         s.erase(it+1,it+sz);
236     }
237 }
238