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