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