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 | |
26 | static Standard_Integer WhatKindOfLine(OSD_File& aFile, |
27 | TCollection_AsciiString& aToken1, |
28 | TCollection_AsciiString& aToken2); |
29 | |
30 | static Standard_Integer GetLine(OSD_File& aFile,TCollection_AsciiString& aLine); |
31 | |
32 | static Standard_Boolean Debug; |
33 | |
34 | Resource_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 | |
54 | Resource_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 | |
87 | void 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 | |
137 | static 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 | |
196 | static 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 | //======================================================================= |
219 | Standard_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 | |
316 | Standard_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 | |
333 | Standard_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 | |
350 | Standard_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 | |
366 | Standard_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 | //======================================================================= |
386 | void 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 | //======================================================================= |
397 | void 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 | //======================================================================= |
408 | void 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 | //======================================================================= |
433 | void 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 | //======================================================================= |
446 | Standard_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 | } |