0027645: Data Exchange - access violation when reading STEP AP242 file
[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
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 36IMPLEMENT_STANDARD_RTTIEXT(Resource_Manager,MMgt_TShared)
37
969d1caf 38//! Auxiliary enumeration for function WhatKindOfLine().
39enum 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
48static Resource_KindOfLine WhatKindOfLine(OSD_File& aFile,
7fd59977 49 TCollection_AsciiString& aToken1,
50 TCollection_AsciiString& aToken2);
51
52static Standard_Integer GetLine(OSD_File& aFile,TCollection_AsciiString& aLine);
53
54static Standard_Boolean Debug;
55
56Resource_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
86Resource_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 111void 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 151static 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
204static 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//=======================================================================
228Standard_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
331Standard_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
348Standard_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
365Standard_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
381Standard_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//=======================================================================
401void 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//=======================================================================
412void 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//=======================================================================
423void 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//=======================================================================
448void 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//=======================================================================
461Standard_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
474void 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}