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