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