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