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