Salome HOME
22308: EDF 2572 SMESH: Can't import a file with a non ascii character in the path
[modules/smesh.git] / src / SMESHUtils / SMESH_File.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
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
20 // File      : SMESH_File.cxx
21 // Created   : Wed Mar 10 11:23:25 2010
22 // Author    : Edward AGAPOV (eap)
23 //
24 #include "SMESH_File.hxx"
25 #include "utilities.h"
26
27 #include <fcntl.h>
28 #include <sys/stat.h>
29
30 #ifdef WIN32
31 #include <io.h>
32 #else
33 #include <unistd.h>
34 #include <sys/mman.h>
35 #endif
36
37 #include <boost/filesystem.hpp>
38
39 namespace boofs = boost::filesystem;
40
41 //================================================================================
42 /*!
43  * \brief Creator opening the file for reading by default
44  */
45 //================================================================================
46
47 SMESH_File::SMESH_File(const std::string& name, bool open)
48   :_name(name), _size(-1), _file(0), _map(0), _pos(0), _end(0)
49 {
50   if ( open ) this->open();
51 }
52
53 //================================================================================
54 /*!
55  * \brief Destructor closing the file
56  */
57 //================================================================================
58
59 SMESH_File::~SMESH_File()
60 {
61   close();
62 }
63
64 //================================================================================
65 /*!
66  * \brief Open file for reading. Return true if there is something to read
67  */
68 //================================================================================
69
70 bool SMESH_File::open()
71 {
72   int length = size();
73   if ( !_map && length > 0 )
74   {
75 #ifdef WIN32
76     _file = CreateFile(_name.data(), GENERIC_READ, FILE_SHARE_READ,
77                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
78     bool ok = ( _file != INVALID_HANDLE_VALUE );
79 #else
80     _file = ::open(_name.data(), O_RDONLY );
81     bool ok = ( _file > 0 );
82 #endif
83     if ( ok )
84     {
85 #ifdef WIN32
86       _mapObj = CreateFileMapping(_file, NULL, PAGE_READONLY, 0, (DWORD)length, NULL);
87       _map = (void*) MapViewOfFile( _mapObj, FILE_MAP_READ, 0, 0, 0 );
88 #else
89       _map = ::mmap(0,length,PROT_READ,MAP_PRIVATE,_file,0);
90       if ( _map == MAP_FAILED ) _map = NULL;
91 #endif
92       if ( _map != NULL )
93       {
94         _size = length;
95         _pos = (char*) _map;
96         _end = _pos + _size;
97       }
98       else
99       {
100 #ifdef WIN32
101         CloseHandle(_mapObj);
102         CloseHandle(_file);
103 #else
104         ::close(_file);
105 #endif
106       }
107     }
108   }
109   return _pos;
110 }
111
112 //================================================================================
113 /*!
114  * \brief Close the file
115  */
116 //================================================================================
117
118 void SMESH_File::close()
119 {
120   if ( _map != NULL )
121   {
122 #ifdef WIN32
123     UnmapViewOfFile(_map);
124     CloseHandle(_mapObj);
125     CloseHandle(_file);
126 #else
127     ::munmap(_map, _size);
128     ::close(_file);
129 #endif
130     _map = NULL;
131     _pos = _end = 0;
132     _size = -1;
133   }
134   else if ( _file >= 0 )
135   {
136 #ifdef WIN32
137     CloseHandle(_file);
138     _file = INVALID_HANDLE_VALUE;
139 #else
140     ::close(_file);
141     _file = -1;
142 #endif
143   }
144 }
145
146 //================================================================================
147 /*!
148  * \brief Remove the file
149  */
150 //================================================================================
151
152 bool SMESH_File::remove()
153 {
154   close();
155
156   boost::system::error_code err;
157   boofs::remove( _name, err );
158   _error = err.message();
159
160   return !err;
161 }
162
163 //================================================================================
164 /*!
165  * \brief Return file size
166  */
167 //================================================================================
168
169 long SMESH_File::size()
170 {
171   if ( _size >= 0 ) return _size; // size of an open file
172
173   boost::system::error_code err;
174   uintmax_t size = boofs::file_size( _name, err );
175   _error = err.message();
176
177   return err ? -1 : (long) size;
178 }
179
180 //================================================================================
181 /*!
182  * \brief Check existence
183  */
184 //================================================================================
185
186 bool SMESH_File::exists()
187 {
188   boost::system::error_code err;
189   bool res = boofs::exists( _name, err );
190   _error = err.message();
191
192   return err ? false : res;
193 }
194
195 //================================================================================
196 /*!
197  * \brief Check existence
198  */
199 //================================================================================
200
201 bool SMESH_File::isDirectory()
202 {
203   boost::system::error_code err;
204   bool res = boofs::is_directory( _name, err );
205   _error = err.message();
206
207   return err ? false : res;
208 }
209
210 //================================================================================
211 /*!
212  * \brief Set cursor to the given position
213  */
214 //================================================================================
215
216 void SMESH_File::setPos(const char* pos)
217 {
218   if ( pos > (const char*)_map && pos < _end )
219     _pos = (char*) pos;
220 }
221
222 //================================================================================
223 /*!
224  * \brief Skip till current line end and return the skipped string
225  */
226 //================================================================================
227
228 std::string SMESH_File::getLine()
229 {
230   std::string line;
231   const char* p = _pos;
232   while ( !eof() )
233     if ( *(++_pos) == '\n' )
234       break;
235   line.append( p, _pos );
236   if ( !eof() ) _pos++;
237   return line;
238 }
239
240 //================================================================================
241 /*!
242  * \brief Move cursor to the file beginning
243  */
244 //================================================================================
245
246 void SMESH_File::rewind()
247 {
248   _pos = (char*) _map;
249 }
250
251 //================================================================================
252 /*!
253  * \brief Fill vector by reading out integers from file. Vector size gives number
254  * of integers to read
255  */
256 //================================================================================
257
258 bool SMESH_File::getInts(std::vector<int>& ints)
259 {
260   int i = 0;
261   while ( i < ints.size() )
262   {
263     while ( !isdigit( *_pos ) && !eof()) ++_pos;
264     if ( eof() ) break;
265     if ( _pos[-1] == '-' ) --_pos;
266     ints[ i++ ] = strtol( _pos, (char**)&_pos, 10 );
267   }
268   return ( i == ints.size() );
269 }
270
271 //================================================================================
272 /*!
273  * \brief Open for binary writing only.
274  */
275 //================================================================================
276
277 bool SMESH_File::openForWriting()
278 {
279 #ifdef WIN32
280
281   _file = CreateFile( _name.c_str(),          // name of the write
282                       GENERIC_WRITE,          // open for writing
283                       0,                      // do not share
284                       NULL,                   // default security
285                       OPEN_ALWAYS,            // CREATE NEW or OPEN EXISTING
286                       FILE_ATTRIBUTE_NORMAL,  // normal file
287                       NULL);                  // no attr. template
288   return ( _file != INVALID_HANDLE_VALUE );
289
290 #else
291
292   _file = ::open( _name.c_str(),
293                   O_WRONLY | O_CREAT,
294                   S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); // rw-r--r--
295   return _file >= 0;
296
297 #endif
298 }
299
300 //================================================================================
301 /*!
302  * \brief Write binary data
303  */
304 //================================================================================
305
306 bool SMESH_File::writeRaw(const void* data, size_t size)
307 {
308 #ifdef WIN32
309
310   DWORD nbWritten = 0;
311   BOOL err = WriteFile( _file, data, size, & nbWritten, NULL);
312
313   return (( err == FALSE ) &&
314           ( nbWritten == (DWORD) size ));
315
316 #else
317
318   ssize_t nbWritten = ::write( _file, data, size );
319   return ( nbWritten == size );
320
321 #endif
322 }