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