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