]> SALOME platform Git repositories - modules/gui.git/blob - src/LightApp/LightApp_Driver.cxx
Salome HOME
3febbba9d97be0f3af35907b9c03605ae4f5aa38
[modules/gui.git] / src / LightApp / LightApp_Driver.cxx
1 #include "LightApp_Driver.h"
2
3 #include <TCollection_AsciiString.hxx> 
4
5 #include <OSD_Path.hxx>
6 #include <OSD_File.hxx>
7 #include <OSD_Directory.hxx>
8 #include <OSD_Process.hxx>
9 #include <OSD_Directory.hxx>
10 #include <OSD_Protection.hxx>
11 #include <OSD_SingleProtection.hxx>
12 #include <OSD_FileIterator.hxx>
13
14 #include <qfileinfo.h>
15 #include <qdir.h>
16
17 #ifdef WIN32
18 #include <time.h>
19 #endif
20
21 /*! Constructor.*/
22 LightApp_Driver::LightApp_Driver()
23 {
24 }
25  
26 /*! Destructor.*/
27 LightApp_Driver::~LightApp_Driver()
28 {
29 }
30
31 using namespace std;
32
33 //================================================================
34 // Function : SaveDatasInFile
35 /*! Purpose  : save in file 'theFileName' datas from this driver*/
36 //================================================================
37 bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile )
38 {
39   int aNbModules = 0;
40   std::map<std::string, ListOfFiles>::const_iterator it;
41   for (it = myMap.begin(); it != myMap.end(); ++it)
42     aNbModules++;
43
44   unsigned char** aBuffer = new unsigned char*[aNbModules]; 
45   long*           aBufferSize = new long[aNbModules];
46   char**          aModuleName = new char*[aNbModules];
47
48   if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL)
49     return false;
50
51   int aFileBufferSize = 4;  //4 bytes for a number of the modules that will be written to the stream;
52   int i = 0;
53   for (it = myMap.begin(); it != myMap.end(); ++it) {
54     aModuleName[i] = const_cast<char*>(it->first.c_str());//(it->first);
55     aFileBufferSize += 4;                                //Add 4 bytes: a length of the module name
56     aFileBufferSize += strlen(aModuleName[i])+1;
57     std::string aName(aModuleName[i]);
58     PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile);
59     aFileBufferSize += 8;                                //Add 8 bytes: a length of the buffer
60     aFileBufferSize += aBufferSize[i];
61     i++;
62   }
63   int n = i;
64
65   unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
66   if(aFileBuffer == NULL)
67     return false;
68
69   myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).dirPath( true ) + "/" ).latin1() ;
70
71   int aCurrentPos = 0;
72
73   //Initialize 4 bytes of the buffer by 0
74   memset(aFileBuffer, 0, 4); 
75   //Copy the number of modules that will be written to the stream
76   memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int)));
77   aCurrentPos += 4;
78
79   int aBufferNameSize = 0;
80   for (i = 0; i < n; i++) {
81     aBufferNameSize = strlen(aModuleName[i])+1;
82     //Initialize 4 bytes of the buffer by 0
83     memset((aFileBuffer + aCurrentPos), 0, 4); 
84     //Copy the length of the module name to the buffer
85     memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int))); 
86     aCurrentPos += 4;
87     //Copy the module name to the buffer
88     memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize);
89     aCurrentPos += aBufferNameSize;
90
91     //Initialize 8 bytes of the buffer by 0
92     memset((aFileBuffer + aCurrentPos), 0, 8);
93     //Copy the length of the module buffer to the buffer
94     memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
95     aCurrentPos += 8;
96     //Copy the module buffer to the buffer
97     memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]);
98     aCurrentPos += aBufferSize[i];
99   }
100
101 #ifdef WNT  
102   ofstream aFile(theFileName, ios::out | ios::binary);
103 #else
104   ofstream aFile(theFileName);
105 #endif
106   aFile.write((char*)aFileBuffer, aFileBufferSize); 
107   aFile.close();    
108
109   delete[] aBuffer;
110   delete[] aBufferSize;
111   delete[] aModuleName;
112   delete[] aFileBuffer;
113
114   return true;
115 }
116
117 //=======================================================================
118 // name    : ReaDatasFromFile
119 /*! Purpose : filling current driver from file 'theFileName'*/
120 //=======================================================================
121 bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile )
122 {
123 #ifdef WNT
124   ifstream aFile(theFileName, ios::binary);
125 #else
126   ifstream aFile(theFileName);
127 #endif  
128
129   myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).dirPath( true ) + "/" ).latin1() ;
130
131   aFile.seekg(0, ios::end);
132   int aFileBufferSize = aFile.tellg();
133   unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
134   aFile.seekg(0, ios::beg);
135   aFile.read((char*)aFileBuffer, aFileBufferSize);
136   aFile.close();
137
138   int aNbModules = 0;
139   //Copy the number of files in the stream
140   memcpy(&aNbModules, aFileBuffer, sizeof(int));
141   long aCurrentPos = 4;
142   int aModuleNameSize;
143
144   for (int i = 0; i < aNbModules; i++) {
145     //Put a length of the module name to aModuleNameSize
146     memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); 
147     aCurrentPos += 4;
148
149     char *aModuleName = new char[aModuleNameSize];
150     //Put a module name to aModuleName
151     memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize); 
152     aCurrentPos += aModuleNameSize;
153
154     //Put a length of the file buffer to aBufferSize
155     long aBufferSize;
156     memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long))); 
157     aCurrentPos += 8;
158     unsigned char *aBuffer = new unsigned char[aBufferSize];
159  
160     //Put a buffer for current module to aBuffer
161     memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize); 
162     aCurrentPos += aBufferSize;
163
164     // Put buffer to aListOfFiles and set to myMap
165     ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile);
166     SetListOfFiles(aModuleName, aListOfFiles);
167
168     delete[] aModuleName;
169     delete[] aBuffer;
170   }
171
172   delete[] aFileBuffer;
173   
174   return true;
175 }
176
177 //================================================================
178 // Function : GetTmpDir
179 /*! Purpose  : returns temp directory for path 'theURL'*/
180 //================================================================
181 std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool  isMultiFile)
182 {
183   std::string anURLDir = GetDirFromPath(theURL);
184   std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir();
185
186   return aTmpDir;
187 }
188
189 //================================================================
190 // Function : GetListOfFiles
191 /*! Purpose  : returns list of files for module with name 'theModuleName'*/
192 //================================================================
193 LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName )
194 {
195   ListOfFiles aListOfFiles;
196
197   std::string aName(theModuleName);
198   if (myMap.count(aName))
199     aListOfFiles = myMap[aName];
200
201     return aListOfFiles;
202 }
203
204 //================================================================
205 // Function : SetListOfFiles
206 /*! Purpose  : sets list of files for module with name 'theModuleName'*/
207 //================================================================
208 void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles )
209 {
210   std::string aName (theModuleName);
211   myMap[aName] = theListOfFiles;
212 }
213
214 //============================================================================
215 // function : PutFilesToStream
216 /*! Purpose  : converts files which was created from module <theModuleName> into a byte sequence unsigned char*/
217 //============================================================================
218 void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer,
219                                         long& theBufferSize, bool theNamesOnly )
220 {
221   ListOfFiles aFiles = myMap[theModuleName];
222   // aFiles must contain temporary directory name in its first item
223   // and names of files (relatively the temporary directory) in the others
224
225   int i, aLength = aFiles.size() - 1;
226   if(aLength <= 0) {
227     theBufferSize = 0;
228     theBuffer = new unsigned char[theBufferSize];
229     return;
230   }
231   //Get a temporary directory for saved a file
232   TCollection_AsciiString aTmpDir(const_cast<char*>(aFiles[0].c_str()));
233
234   long aBufferSize = 0;
235   long aCurrentPos;
236   int aNbFiles = 0;
237   int* aFileNameSize= new int[aLength];
238   long* aFileSize= new long[aLength];
239
240   //Determine the required size of the buffer
241   TCollection_AsciiString aFileName;
242   for (i = 0; i < aLength; i++) {
243     char* aFName = const_cast<char*>(aFiles[i+1].c_str());
244     aFileName = aFName;
245     //Check if the file exists
246     if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero
247       TCollection_AsciiString aFullPath = aTmpDir + aFileName;   
248       OSD_Path anOSDPath(aFullPath);
249       OSD_File anOSDFile(anOSDPath);
250       if(!anOSDFile.Exists()) continue;
251 #ifdef WNT
252       ifstream aFile(aFullPath.ToCString(), ios::binary);
253 #else
254       ifstream aFile(aFullPath.ToCString());
255 #endif
256       aFile.seekg(0, ios::end);
257       aFileSize[i] = aFile.tellg();
258       aBufferSize += aFileSize[i];              //Add a space to store the file
259     }
260     aFileNameSize[i] = strlen(aFName) + 1;
261     aBufferSize += aFileNameSize[i];          //Add a space to store the file name
262     aBufferSize += (theNamesOnly)?4:12;       //Add 4 bytes: a length of the file name,
263                                               //    8 bytes: length of the file itself
264     aNbFiles++;
265   }
266
267   aBufferSize += 4;      //4 bytes for a number of the files that will be written to the stream;
268   theBuffer = new unsigned char[aBufferSize];  
269   if(theBuffer == NULL) {
270     theBufferSize = 0;
271     theBuffer = 0;
272     return;
273   }
274   //Initialize 4 bytes of the buffer by 0
275   memset(theBuffer, 0, 4); 
276   //Copy the number of files that will be written to the stream
277   memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int))); 
278
279   aCurrentPos = 4;
280
281   for(i = 0; i < aLength; i++) {
282     ifstream *aFile;
283     if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true
284       TCollection_AsciiString aName(const_cast<char*>(aFiles[i+1].c_str()));
285       TCollection_AsciiString aFullPath = aTmpDir + aName;
286       OSD_Path anOSDPath(aFullPath);
287       OSD_File anOSDFile(anOSDPath);
288       if(!anOSDFile.Exists()) continue;
289 #ifdef WNT
290       aFile = new ifstream(aFullPath.ToCString(), ios::binary);
291 #else
292       aFile = new ifstream(aFullPath.ToCString());
293 #endif
294     }
295     //Initialize 4 bytes of the buffer by 0
296     memset((theBuffer + aCurrentPos), 0, 4); 
297     //Copy the length of the file name to the buffer
298     memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int))); 
299     aCurrentPos += 4;
300
301     //Copy the file name to the buffer
302     char* aFName = const_cast<char*>(aFiles[i+1].c_str());
303     memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]);
304     aCurrentPos += aFileNameSize[i];
305     
306     if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly
307       //Initialize 8 bytes of the buffer by 0
308       memset((theBuffer + aCurrentPos), 0, 8); 
309       //Copy the length of the file to the buffer
310       memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
311       aCurrentPos += 8;
312       
313       aFile->seekg(0, ios::beg);
314       aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]);
315       aFile->close();
316       delete(aFile);
317       aCurrentPos += aFileSize[i];
318     }
319   }
320   delete[] aFileNameSize;
321   delete[] aFileSize;
322
323   theBufferSize = aBufferSize;
324 }
325
326 //============================================================================
327 // function : PutStreamToFile
328 /*! Purpose  : converts a byte sequence <theBuffer> to files and return list of them*/
329 //============================================================================
330 LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer,
331                                                                 const long theBufferSize, bool theNamesOnly )
332 {
333   if(theBufferSize == 0 || theBuffer == 0)
334     return   ListOfFiles();
335
336   // Create a temporary directory for the component's data files
337   std::string aDir = GetTmpDir();
338
339   //Get a temporary directory for saving a file
340   TCollection_AsciiString aTmpDir(const_cast<char*>(aDir.c_str()));
341
342   long aFileSize, aCurrentPos = 4;
343   int i, aFileNameSize, aNbFiles = 0;
344
345   //Copy the number of files in the stream
346   memcpy(&aNbFiles, theBuffer, sizeof(int)); 
347
348   const int n = aNbFiles + 1;
349   ListOfFiles aFiles(n);
350   aFiles[0] = aDir;
351
352   for(i = 0; i < aNbFiles; i++) {
353     //Put a length of the file name to aFileNameSize
354     memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int))); 
355     aCurrentPos += 4;
356
357     char *aFileName = new char[aFileNameSize];
358     //Put a file name to aFileName
359     memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize); 
360     aCurrentPos += aFileNameSize;
361  
362     //Put a length of the file to aFileSize
363     if (!theNamesOnly) {
364       memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
365       aCurrentPos += 8;    
366       
367       TCollection_AsciiString aFullPath = aTmpDir + aFileName;
368       
369 #ifdef WNT  
370   ofstream aFile(aFullPath.ToCString(), ios::out | ios::binary);
371 #else
372   ofstream aFile(aFullPath.ToCString());
373 #endif
374
375       aFile.write((char *)(theBuffer+aCurrentPos), aFileSize); 
376       aFile.close();  
377       aCurrentPos += aFileSize;
378     }
379     std::string aStrFileName(aFileName);
380     aFiles[i+1] = aStrFileName;
381     delete[] aFileName;
382   }
383   return aFiles;
384 }
385
386 //============================================================================
387 // function : RemoveFiles
388 /*! Purpose  : Remove files. First item in <theFiles> is a directory with slash at the end.
389                Other items are names of files. If <IsDirDeleted> is true,
390                then the directory is also deleted.
391 */
392 //============================================================================
393 void LightApp_Driver::RemoveFiles( const ListOfFiles& theFiles, const bool IsDirDeleted)
394 {
395   int i, aLength = theFiles.size() - 1;
396   if(aLength <= 0) {
397     return;
398   }
399   //Get a temporary directory for saved a file
400   TCollection_AsciiString aDirName(const_cast<char*>(theFiles[0].c_str()));
401
402   for(i = 0; i < aLength; i++) {
403     TCollection_AsciiString aFile(aDirName);
404     aFile += const_cast<char*>(theFiles[i+1].c_str());
405     OSD_Path anOSDPath(aFile);
406     OSD_File anOSDFile(anOSDPath);
407     if(!anOSDFile.Exists()) continue;
408
409     anOSDFile.Remove();
410   }
411
412   if(IsDirDeleted) {
413     OSD_Path aPath(aDirName);
414     OSD_Directory aDir(aPath);
415     OSD_FileIterator anIterator(aPath, '*');
416
417     if(aDir.Exists() && !anIterator.More()) aDir.Remove();
418   }
419 }
420
421 //============================================================================
422 // function : RemoveTemporaryFiles
423 /*! Purpose  : removes files which was created from module theModuleName if 
424                <IsDirDeleted> is true tmp directory is also deleted if it is empty*/
425 //============================================================================
426 void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted )
427 {
428   std::string aModuleName(theModuleName);
429   ListOfFiles aFiles = myMap[aModuleName];
430   // aFiles must contain temporary directory name in its first item
431   // and names of files (relatively the temporary directory) in the others
432   RemoveFiles( aFiles, IsDirDeleted );
433
434 }
435
436 //============================================================================
437 // function : ClearDriverContents
438 /*! Purpose  : clear map of list files*/ 
439 //============================================================================ 
440 void LightApp_Driver::ClearDriverContents()
441 {
442   std::map<std::string, ListOfFiles>::iterator it;
443   for ( it = myMap.begin(); it != myMap.end(); ++it ) 
444   {
445     const char* aModuleName = const_cast<char*>(it->first.c_str());
446     RemoveTemporaryFiles( aModuleName, false );
447   }
448   myMap.clear();
449 }
450
451 //============================================================================
452 // function : GetTempDir
453 /*! Purpose  : return a temp directory to store created files like "/tmp/sub_dir/" */
454 //============================================================================ 
455 std::string LightApp_Driver::GetTmpDir()
456 {
457   if ( myTmpDir.length() != 0 )
458     return myTmpDir;
459
460   //Find a temporary directory to store a file
461   TCollection_AsciiString aTmpDir;
462
463   char *Tmp_dir = getenv("SALOME_TMP_DIR");
464   if ( !Tmp_dir )
465     Tmp_dir = getenv ( "TEMP" );
466   if ( !Tmp_dir )
467     Tmp_dir = getenv ( "TMP" );
468   if ( Tmp_dir ) 
469   {
470     aTmpDir = TCollection_AsciiString(Tmp_dir);
471 #ifdef WIN32
472     if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
473 #else
474     if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
475 #endif      
476   }
477   else 
478   {
479 #ifdef WIN32
480     aTmpDir = TCollection_AsciiString("C:\\");
481 #else
482     aTmpDir = TCollection_AsciiString("/tmp/");
483 #endif
484   }
485
486   srand((unsigned int)time(NULL));
487   int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory
488   TCollection_AsciiString aSubDir(aRND);
489   if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876");
490
491   aTmpDir += aSubDir; //Get RND sub directory
492
493 #ifdef WIN32
494   if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
495 #else
496   if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
497 #endif
498
499   OSD_Path aPath(aTmpDir);
500   OSD_Directory aDir(aPath);
501
502   for(aRND = 0; aDir.Exists(); aRND++) {
503     aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND));  //Build a unique directory name
504     aPath = OSD_Path(aTmpDir);
505     aDir = OSD_Directory(aPath);
506   }
507
508   OSD_Protection aProtection(OSD_RW, OSD_RWX, OSD_RX, OSD_RX);
509   aDir.Build(aProtection);
510
511   myTmpDir = aTmpDir.ToCString();
512
513   return aTmpDir.ToCString();
514 }
515
516 //============================================================================
517 // function : GetDirFromPath
518 /*! Purpose  : returns the dir by the path*/
519 //============================================================================
520 std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) {
521   if(thePath == "")
522     return "";
523   OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast<char*>(thePath.c_str())));
524   TCollection_AsciiString aDirString(aPath.Trek());
525   aDirString.ChangeAll('|','/');
526   return aDirString.ToCString();
527 }
528