0026316: Infinite modification of the shapes in General Fuse operation
[occt.git] / src / Resource / Resource_Manager.cxx
CommitLineData
b311480e 1// Copyright (c) 1998-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15#include <Resource_Manager.hxx>
16#include <Resource_Manager.ixx>
17#include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
18#include <Resource_QuickSortOfArray1.hxx>
19#include <Resource_LexicalCompare.hxx>
20
21#include <OSD_Path.hxx>
22#include <OSD_File.hxx>
23#include <OSD_Directory.hxx>
24#include <OSD_Protection.hxx>
25
26#include <Standard_ErrorHandler.hxx>
27#include <TCollection_ExtendedString.hxx>
28#include <Resource_Unicode.hxx>
29#include <TColStd_Array1OfAsciiString.hxx>
30
31#include <errno.h>
32
33#define END 0
34#define EMPTY 1
35#define COMMENT 2
36#define INCLUDE 3
37#define RESOURCE 4
38#define ERROR -1
39
40static Standard_Integer WhatKindOfLine(OSD_File& aFile,
41 TCollection_AsciiString& aToken1,
42 TCollection_AsciiString& aToken2);
43
44static Standard_Integer GetLine(OSD_File& aFile,TCollection_AsciiString& aLine);
45
46static Standard_Boolean Debug;
47
48Resource_Manager::Resource_Manager(const Standard_CString aName,
49 TCollection_AsciiString& aDefaultsDirectory,
50 TCollection_AsciiString& anUserDefaultsDirectory,
51 const Standard_Boolean Verbose) : myName(aName), myVerbose(Verbose)
52{
53 if ( !aDefaultsDirectory.IsEmpty() ) {
54 Load(aDefaultsDirectory,myName,myRefMap);
55 }
56 else
57 if (myVerbose)
58 cout << "Resource Manager Warning: aDefaultsDirectory is empty." << endl;
59
60 if ( !anUserDefaultsDirectory.IsEmpty() ) {
61 Load(anUserDefaultsDirectory,myName,myRefMap);
62 }
63 else
64 if (myVerbose)
65 cout << "Resource Manager Warning: anUserDefaultsDirectory is empty." << endl;
66}
67
68Resource_Manager::Resource_Manager(const Standard_CString aName,
69 const Standard_Boolean Verbose) : myName(aName), myVerbose(Verbose)
70{
71 Debug = (getenv("ResourceDebug") != NULL) ;
72
73 TCollection_AsciiString EnvVar, CSF_ = "CSF_" ;
74 TCollection_AsciiString Directory ;
75 Standard_CString dir ;
76
77 if ( getenv ("CSF_ResourceVerbose") != NULL )
78 myVerbose = Standard_True;
79
80 EnvVar = CSF_ + aName + "Defaults" ;
81 if ((dir = getenv (EnvVar.ToCString())) != NULL) {
82 Directory = dir;
83 Load(Directory,myName,myRefMap);
84 }
85 else
86 if (myVerbose)
87 cout << "Resource Manager Warning: Environment variable \"" << EnvVar
88 << "\" not set." << endl;
89
90 EnvVar = CSF_ + aName + "UserDefaults" ;
91 if ((dir = getenv (EnvVar.ToCString())) != NULL) {
92 Directory = dir;
93 Load(Directory, myName, myUserMap);
94 }
95 else
96 if (myVerbose)
97 cout << "Resource Manager Warning: Environment variable \"" << EnvVar
98 << "\" not set." << endl;
99}
100
101void Resource_Manager::Load(TCollection_AsciiString& aDirectory,
102 TCollection_AsciiString& aName,
103 Resource_DataMapOfAsciiStringAsciiString& aMap)
104{
105 Standard_Integer Kind, Pos;
106 TCollection_AsciiString Token1, Token2;
107 TCollection_AsciiString Directory, Name;
108 TCollection_AsciiString FileName;
109 FileName = aDirectory + "/" + aName;
110 OSD_File File = OSD_Path(FileName);
111 File.Open(OSD_ReadOnly,OSD_Protection());
112 if (File.Failed()) {
113 if (myVerbose)
114 cout << "Resource Manager Warning: Cannot read file \"" << FileName
115 << "\". File not found or permission denied." << endl;
116 return;
117 }
118 Standard_Integer LineNumber = 1;
119 while ((Kind = WhatKindOfLine(File, Token1, Token2)) != END) {
120 switch (Kind) {
121 case COMMENT :
122 case EMPTY :
123 break ;
124 case INCLUDE :
125 Directory = OSD_Path::AbsolutePath(aDirectory,Token1);
126 Pos = Directory.SearchFromEnd("/");
127 if (Pos != 0) {
128 Name = Directory.Split(Pos);
129 Directory.Trunc(Pos-1);
130 Load(Directory,Name,aMap);
131 }
132 break;
133 case RESOURCE :
134 if (!aMap.Bind(Token1,Token2))
135 aMap(Token1) = Token2;
136 break;
137 case ERROR :
138 if (myVerbose)
139 cout << "Resource Manager: Syntax error at line "
140 << LineNumber << " in file : " << FileName << endl;
141 break;
142 }
143 LineNumber++;
144 }
145 File.Close();
146 if (myVerbose)
147 cout << "Resource Manager: " << ((&aMap == &myUserMap) ? "User" : "Reference")
148 << " file \"" << FileName << "\" loaded" << endl;
149}
150
151static Standard_Integer WhatKindOfLine(OSD_File& aFile,
152 TCollection_AsciiString& aToken1,
153 TCollection_AsciiString& aToken2)
154{
155 TCollection_AsciiString WhiteSpace = " \t" ;
156 Standard_Integer Pos1,Pos2,Pos ;
157 TCollection_AsciiString Line ;
158
159 if (!GetLine(aFile,Line))
160 return END;
161
162 if (Line.Value(1) == '!')
163 return COMMENT;
164
165 if (Line.Value(1) == '#') {
166 Line.Remove(1);
167 if ((Line.Token(" \t")).IsDifferent("include"))
168 return ERROR;
169
170 aToken1 = Line.Token(" \t\n",2);
171 return INCLUDE;
172 }
173
174 Pos1 = Line.FirstLocationNotInSet(WhiteSpace, 1, Line.Length());
175 if (Line.Value(Pos1) == '\n')
176 return EMPTY;
177
178 Pos2 = Line.Location(1,':',Pos1,Line.Length());
179 if (!Pos2 || Pos1 == Pos2)
180 return ERROR;
181
182 for (Pos = Pos2-1; Line.Value(Pos) == '\t' || Line.Value(Pos) == ' ' ; Pos--);
183 aToken1 = Line.SubString(Pos1, Pos);
184
185 if (Debug)
186 cout << "Key = '" << aToken1 << flush ;
187
302f96fb 188 Pos = Line.FirstLocationNotInSet(WhiteSpace, Pos2+1, Line.Length());
189 if (Pos) {
7fd59977 190 if (Line.Value(Pos) == '\\')
191 switch(Line.Value(Pos+1)) {
192 case '\\' :
193 case ' ' :
194 case '\t' :
195 Pos++;
196 break;
197 }
198 }
199 if (Pos == Line.Length())
200 aToken2.Clear();
bcf50875 201 else {
202 Line.Remove(1,Pos-1);
203 Line.Remove(Line.Length());
204 aToken2 = Line;
205 }
7fd59977 206 if (Debug)
207 cout << "'\t Value = '" << aToken2 << "'" << endl << flush;
208 return RESOURCE;
209}
210
211// Retourne 0 (EOF) ou une ligne toujours terminee par <NL>.
212
213static Standard_Integer GetLine(OSD_File& aFile,TCollection_AsciiString& aLine)
214{
215 TCollection_AsciiString Buffer;
216 Standard_Integer BufSize = 10;
217 Standard_Integer Len;
218
219 aLine.Clear();
220 do {
221 aFile.ReadLine(Buffer,BufSize,Len);
222 aLine += Buffer;
eafb234b 223 if (aFile.IsAtEnd()) {
7fd59977 224 if (!aLine.Length()) return 0;
225 else aLine += "\n";
eafb234b 226 }
7fd59977 227 } while (aLine.Value(aLine.Length()) != '\n');
228
229 return 1;
230}
231
232//=======================================================================
233//function : Save
234//purpose : Sort and save the user resources in the user file.
235// Creates the file if it does not exist.
236//=======================================================================
237Standard_Boolean Resource_Manager::Save() const
238{
239 Standard_Integer Index;
240 TCollection_AsciiString EnvVar, CSF_ = "CSF_";
241 Standard_CString dir;
242
243 EnvVar = CSF_ + myName + "UserDefaults";
244
245 if ((dir = getenv (EnvVar.ToCString())) == NULL) {
246 if (myVerbose)
247 cout << "Resource Manager Warning: environment variable \""
248 << EnvVar << "\" not set. Cannot save resources." << endl ;
249 return Standard_False;
250 }
251 TCollection_AsciiString FilePath = dir;
252 OSD_Directory Dir = OSD_Path(FilePath);
253 Standard_Boolean Status = Standard_True;
254 if ( !Dir.Exists() ) {
255 {
256 try {
257 OCC_CATCH_SIGNALS
258 Dir.Build(OSD_Protection(OSD_RX, OSD_RWX, OSD_RX, OSD_RX));
259 }
260 catch (Standard_Failure) {
261 Status = Standard_False;
262 }
263 }
264 Status = Status && !Dir.Failed();
265 if (!Status) {
266 if (myVerbose)
267 cout << "Resource Manager: Error opening or creating directory \"" << FilePath
268 << "\". Permission denied. Cannot save resources." << endl;
269 return Standard_False;
270 }
271 }
272
273 FilePath += "/"; FilePath += myName;
274 OSD_Path Path(FilePath);
275 OSD_File File = Path;
276 OSD_Protection theProt;
277 Status = Standard_True;
278 {
279 try {
280 OCC_CATCH_SIGNALS
281 File.Build(OSD_ReadWrite, theProt);
282 }
283 catch (Standard_Failure) {
284 Status = Standard_False;
285 }
286 }
287 Status = Status && !File.Failed();
288 if (!Status) {
289 if (myVerbose)
290 cout << "Resource Manager: Error opening or creating file \"" << FilePath
291 << "\". Permission denied. Cannot save resources." << endl;
292 return Standard_False;
293 }
294
295 Resource_LexicalCompare Comp;
296 Standard_Integer NbKey = myUserMap.Extent();
174178b9 297 TColStd_Array1OfAsciiString KeyArray(1,NbKey+1); // 1 more item is added to allow saving empty resource
7fd59977 298 Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString Iter(myUserMap);
299
300 for ( Index = 1; Iter.More(); Iter.Next())
301 KeyArray(Index++)= Iter.Key();
302
303 Resource_QuickSortOfArray1::Sort(KeyArray, Comp);
304
305 TCollection_AsciiString Line, Value;
306 for (Index = 1 ; Index <= NbKey ; Index++) {
307 Value = myUserMap(KeyArray(Index));
308 if (!Value.IsEmpty())
309 switch(Value.Value(1)) {
310 case '\\' :
311 case ' ' :
312 case '\t' :
313 Value.Insert(1,'\\');
314 break;
315 }
316 Line = KeyArray(Index) + ":\t" + Value + "\n";
317
318 if (Debug)
319 cout << "Line = '" << Line << "'" << endl;
320
321 File.Write(Line, Line.Length());
322 }
323 if (myVerbose)
324 cout << "Resource Manager: Resources saved in file " << FilePath << endl;
325 File.Close();
326 return Standard_True;
327}
328
329//=======================================================================
330//function : Integer
331//purpose : Gets the value of an integer resource
332//=======================================================================
333
334Standard_Integer Resource_Manager::Integer(const Standard_CString aResourceName) const
335{
336 TCollection_AsciiString Result = Value(aResourceName) ;
337 if (!Result.IsIntegerValue()) {
338 TCollection_AsciiString n("Value of resource `");
339 n+= aResourceName;
340 n+= "` is not an integer";
341 Standard_TypeMismatch::Raise(n.ToCString());
342 }
343 return Result.IntegerValue();
344}
345
346//=======================================================================
347//function : Real
348//purpose : Gets the value of a real resource
349//=======================================================================
350
351Standard_Real Resource_Manager::Real(const Standard_CString aResourceName) const
352{
353 TCollection_AsciiString Result = Value(aResourceName) ;
354 if (!Result.IsRealValue()) {
355 TCollection_AsciiString n("Value of resource `");
356 n+= aResourceName;
357 n+= "` is not a real";
358 Standard_TypeMismatch::Raise(n.ToCString());
359 }
360 return Result.RealValue();
361}
362
363//=======================================================================
364//function : Value
365//purpose : Gets the value of a CString resource
366//=======================================================================
367
368Standard_CString Resource_Manager::Value(const Standard_CString aResource) const
369{
370 TCollection_AsciiString Resource(aResource);
371 if (myUserMap.IsBound(Resource))
372 return myUserMap(Resource).ToCString();
373 if (myRefMap.IsBound(Resource))
374 return myRefMap(Resource).ToCString();
375 Resource_NoSuchResource::Raise(aResource);
376 return ("");
377}
378
379//=======================================================================
380//function : ExtValue
381//purpose : Gets the value of a ExtString resource
382//=======================================================================
383
384Standard_ExtString Resource_Manager::ExtValue(const Standard_CString aResource)
385{
386 TCollection_AsciiString Resource(aResource);
387 if (myExtStrMap.IsBound(Resource))
388 return myExtStrMap(Resource).ToExtString();
389
390 TCollection_AsciiString Result = Value(aResource);
391 TCollection_ExtendedString ExtResult;
392
393 Resource_Unicode::ConvertFormatToUnicode(Result.ToCString(),ExtResult);
394
395 myExtStrMap.Bind(Resource, ExtResult);
396 return myExtStrMap(Resource).ToExtString();
397}
398
399//=======================================================================
400//function : SetResource
401//purpose : Sets the new value of an integer resource.
402// If the resource does not exist, it is created.
403//=======================================================================
404void Resource_Manager::SetResource(const Standard_CString aResourceName,
405 const Standard_Integer aValue)
406{
407 SetResource(aResourceName,TCollection_AsciiString(aValue).ToCString());
408}
409
410//=======================================================================
411//function : SetResource
412//purpose : Sets the new value of a real resource.
413// If the resource does not exist, it is created.
414//=======================================================================
415void Resource_Manager::SetResource(const Standard_CString aResourceName,
416 const Standard_Real aValue)
417{
418 SetResource(aResourceName,TCollection_AsciiString(aValue).ToCString());
419}
420
421//=======================================================================
422//function : SetResource
423//purpose : Sets the new value of ExtString resource.
424// If the resource does not exist, it is created.
425//=======================================================================
426void Resource_Manager::SetResource(const Standard_CString aResource,
427 const Standard_ExtString aValue)
428{
429 Standard_PCharacter pStr;
430 TCollection_AsciiString Resource = aResource;
431 TCollection_ExtendedString ExtValue = aValue;
432 TCollection_AsciiString FormatStr(ExtValue.Length()*3+10, ' ');
433
434 if (!myExtStrMap.Bind(Resource,ExtValue)) {
435 myExtStrMap(Resource) = ExtValue;
436 }
437 //
438 pStr=(Standard_PCharacter)FormatStr.ToCString();
439 //
440 Resource_Unicode::ConvertUnicodeToFormat(ExtValue,
441 pStr,//FormatStr.ToCString(),
442 FormatStr.Length()) ;
443 SetResource(aResource,FormatStr.ToCString());
444}
445
446//=======================================================================
447//function : SetResource
448//purpose : Sets the new value of an enum resource.
449// If the resource does not exist, it is created.
450//=======================================================================
451void Resource_Manager::SetResource(const Standard_CString aResource,
452 const Standard_CString aValue)
453{
454 TCollection_AsciiString Resource = aResource;
455 TCollection_AsciiString Value = aValue;
456 if (!myUserMap.Bind(Resource, Value))
457 myUserMap(Resource) = Value;
458}
459
460//=======================================================================
461//function : Find
462//purpose : Tells if a resource exits.
463//=======================================================================
464Standard_Boolean Resource_Manager::Find(const Standard_CString aResource) const
465{
466 TCollection_AsciiString Resource(aResource);
467 if (myUserMap.IsBound(Resource) || myRefMap.IsBound(Resource))
468 return Standard_True;
469 return Standard_False;
470}