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