0030550: Coding - Integer overflow in Standard_CString HashCodes
[occt.git] / src / Standard / Standard_Type.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
69ff08ff 16#include <Standard_Type.hxx>
17#include <Standard_Mutex.hxx>
18#include <Standard_Assert.hxx>
7fd59977 19
69ff08ff 20#include <NCollection_DataMap.hxx>
7fd59977 21
f5f4ebd0 22IMPLEMENT_STANDARD_RTTIEXT(Standard_Type,Standard_Transient)
23
7fd59977 24//============================================================================
25
a0218ba1
RL
26namespace {
27static Standard_CString copy_string (const char* theString)
28{
29 size_t aLength = strlen (theString);
30 char* aResult = static_cast<char*> (Standard::Allocate (aLength + 1));
31 strncpy (aResult, theString, aLength + 1); //including null-character
32 return aResult;
33}
34}
35
36Standard_Type::Standard_Type (const char* theSystemName,
37 const char* theName,
38 Standard_Size theSize,
39 const Handle(Standard_Type)& theParent) :
795be040 40 mySystemName(copy_string (theSystemName)),
41 myName(copy_string (theName)),
42 mySize(theSize),
43 myParent(theParent)
a0218ba1
RL
44{
45}
46
47//============================================================================
48
69ff08ff 49Standard_Boolean Standard_Type::SubType (const Handle(Standard_Type)& theOther) const
7fd59977 50{
69ff08ff 51 return ! theOther.IsNull() && (theOther == this || (! myParent.IsNull() && myParent->SubType (theOther)));
7fd59977 52}
53
7fd59977 54//============================================================================
55
69ff08ff 56Standard_Boolean Standard_Type::SubType (const Standard_CString theName) const
7fd59977 57{
42a9dcfc 58 return theName != 0 && (IsEqual (myName, theName) || (! myParent.IsNull() && myParent->SubType (theName)));
7fd59977 59}
60
69ff08ff 61// ------------------------------------------------------------------
62// Print (me; s: in out OStream) returns OStream;
63// ------------------------------------------------------------------
64void Standard_Type::Print (Standard_OStream& AStream) const
7fd59977 65{
69ff08ff 66 AStream << hex << (Standard_Address)this << " : " << dec << myName ;
7fd59977 67}
68
69//============================================================================
69ff08ff 70// Registry of types
7fd59977 71//============================================================================
7fd59977 72
69ff08ff 73namespace {
74 // Value-based hasher for plain C string (char*)
75 struct CStringHasher
76 {
2b2be3fb 77 //! Computes a hash code of the given Standard_CString, in the range [1, theUpperBound]
78 //! @param theKey the key which hash code is to be computed
79 //! @param theUpperBound the upper bound of the range a computing hash code must be within
80 //! @return a computed hash code, in the range [1, theUpperBound]
81 static Standard_Integer HashCode (const Standard_CString& theKey, const Standard_Integer theUpperBound)
69ff08ff 82 {
2b2be3fb 83 return ::HashCode (theKey, theUpperBound);
69ff08ff 84 }
85 static bool IsEqual (const Standard_CString& theKey1, const Standard_CString& theKey2)
86 {
87 return ! strcmp (theKey1, theKey2);
88 }
89 };
7fd59977 90
69ff08ff 91 // Map of string to type
92 typedef NCollection_DataMap<Standard_CString, Standard_Type*, CStringHasher> registry_type;
7fd59977 93
69ff08ff 94 // Registry is made static in the function to ensure that it gets
95 // initialized by the time of first access
96 registry_type& GetRegistry()
97 {
98 static registry_type theRegistry;
99 return theRegistry;
100 }
7fd59977 101}
102
e7195ab4 103Standard_Type* Standard_Type::Register (const char* theSystemName, const char* theName,
104 Standard_Size theSize, const Handle(Standard_Type)& theParent)
7fd59977 105{
69ff08ff 106 // Access to registry is protected by mutex; it should not happen often because
107 // instances are cached by Standard_Type::Instance() (one per binary module)
108 static Standard_Mutex theMutex;
109 Standard_Mutex::Sentry aSentry (theMutex);
7fd59977 110
69ff08ff 111 // return existing descriptor if already in the registry
112 registry_type& aRegistry = GetRegistry();
113 Standard_Type* aType = 0;
114 if (aRegistry.Find (theSystemName, aType))
115 return aType;
7fd59977 116
69ff08ff 117 // else create a new descriptor
118 aType = new Standard_Type (theSystemName, theName, theSize, theParent);
7fd59977 119
69ff08ff 120 // then add it to registry and return (the reference to the handle stored in the registry)
a0218ba1 121 aRegistry.Bind (aType->mySystemName, aType);
7fd59977 122
69ff08ff 123// cout << "Registering " << theSystemName << ": " << aRegistry.Extent() << endl;
7fd59977 124
69ff08ff 125 return aType;
7fd59977 126}
127
69ff08ff 128Standard_Type::~Standard_Type ()
7fd59977 129{
69ff08ff 130 // remove descriptor from the registry
131 registry_type& aRegistry = GetRegistry();
132 Standard_ASSERT(aRegistry.UnBind (mySystemName), "Standard_Type::~Standard_Type() cannot find itself in registry",);
7fd59977 133
69ff08ff 134// cout << "Unregistering " << mySystemName << ": " << aRegistry.Extent() << endl;
a0218ba1 135 Standard::Free (mySystemName);
795be040 136 Standard::Free (myName);
7fd59977 137}