1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/LDOM/LDOM_MemManager.cxx
tiv 0423218095 0030895: Coding Rules - specify std namespace explicitly for std::cout and streams
"endl" manipulator for Message_Messenger is renamed to "Message_EndLine".

The following entities from std namespace are now used
with std:: explicitly specified (from Standard_Stream.hxx):
std::istream,std::ostream,std::ofstream,std::ifstream,std::fstream,
std::filebuf,std::streambuf,std::streampos,std::ios,std::cout,std::cerr,
std::cin,std::endl,std::ends,std::flush,std::setw,std::setprecision,
std::hex,std::dec.
2019-08-16 12:16:38 +03:00

354 lines
12 KiB
C++

// Created on: 2001-06-26
// Created by: Alexander GRIGORIEV
// Copyright (c) 2001-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <LDOM_MemManager.hxx>
#include <LDOMBasicString.hxx>
IMPLEMENT_STANDARD_RTTIEXT(LDOM_MemManager,Standard_Transient)
#define HASH_MASK 255
#define MINIMAL_ROOM 3
typedef unsigned char LDOM_HashValue; // allocating HASH_MASK integer
inline Standard_Integer convertBlockSize (const Standard_Integer aBlockSize)
{
return ((aBlockSize - 1) / sizeof(Standard_Integer)) + 1;
}
inline Standard_Boolean compareStrings (char * const str,
const char * theString,
const Standard_Integer theLength)
{
// ** This is a bit dangerous (can override the boundary of allocated memory)
// return (str[theLength] == '\0' &&
// memcmp (str, theString, theLength) == 0);
// ** This is a more stable (less performant) solution
if (memcmp (str, theString, theLength)) return Standard_False;
return (str[theLength] == '\0');
}
//=======================================================================
//function : MemBlock::MemBlock
//purpose :
//=======================================================================
inline LDOM_MemManager::MemBlock::MemBlock (const Standard_Integer aSize,
LDOM_MemManager::MemBlock * aFirst)
: mySize (aSize), myNext (aFirst)
{
myFreeSpace = myBlock = new Standard_Integer [aSize];
myEndBlock = myBlock + aSize;
}
//=======================================================================
//function : MemBlock::Allocate
//purpose :
//=======================================================================
inline void * LDOM_MemManager::MemBlock::Allocate (const Standard_Integer aSize)
{
void * aResult = NULL;
if (aSize <= myEndBlock - myFreeSpace) {
aResult = myFreeSpace;
myFreeSpace += aSize;
}
return aResult;
}
//=======================================================================
//function : MemBlock::AllocateAndCheck
//purpose :
//=======================================================================
void * LDOM_MemManager::MemBlock::AllocateAndCheck
(const Standard_Integer aSize,
const LDOM_MemManager::MemBlock *& aFirstWithoutRoom)
{
void * aResult = NULL;
Standard_Integer aRoom = (Standard_Integer)(myEndBlock - myFreeSpace);
if (aSize <= aRoom) {
aResult = myFreeSpace;
myFreeSpace += aSize;
}
if (aRoom < MINIMAL_ROOM) {
if (aFirstWithoutRoom == NULL) aFirstWithoutRoom = this;
} else
aFirstWithoutRoom = NULL;
return aResult;
}
//=======================================================================
//function : ~MemBlock
//purpose : Destructor
//=======================================================================
LDOM_MemManager::MemBlock::~MemBlock ()
{
delete [] myBlock;
MemBlock* aNext = myNext;
while (aNext)
{
MemBlock* aNextNext = aNext->myNext;
aNext->myNext = 0;
delete aNext;
aNext = aNextNext;
}
}
//=======================================================================
//function : HashTable
//purpose : Constructor
//=======================================================================
LDOM_MemManager::HashTable::HashTable (/* const Standard_Integer aMask, */
LDOM_MemManager& aMemManager)
: myManager (aMemManager)
{
Standard_Integer m, nKeys = HASH_MASK + 1;
/*
Standard_Integer m = aMask;
Standard_Integer nKeys = 1;
while (m) {
nKeys *= 2;
m /= 2;
}
myMask = nKeys - 1;
*/
myTable = (TableItem *) myManager.Allocate (sizeof(TableItem) * nKeys);
for (m = 0; m < nKeys; m += 2) {
myTable[m].str = NULL;
myTable[m].next = NULL;
myTable[m+1].str = NULL;
myTable[m+1].next = NULL;
}
}
//=======================================================================
//function : Hash
//purpose : CRC-16 hash function
//=======================================================================
Standard_Integer LDOM_MemManager::HashTable::Hash (const char * aString,
const Standard_Integer aLen)
{
static const unsigned int wCRC16a[16] =
{
0000000, 0140301, 0140601, 0000500,
0141401, 0001700, 0001200, 0141101,
0143001, 0003300, 0003600, 0143501,
0002400, 0142701, 0142201, 0002100,
};
static const unsigned int wCRC16b[16] =
{
0000000, 0146001, 0154001, 0012000,
0170001, 0036000, 0024000, 0162001,
0120001, 0066000, 0074000, 0132001,
0050000, 0116001, 0104001, 0043000,
};
unsigned int aCRC = 0;
const unsigned char * aPtr = (const unsigned char *) aString;
for (Standard_Integer i = aLen; i > 0; i--) {
const unsigned int bTmp = aCRC ^ (unsigned int) (* aPtr++);
aCRC = ((aCRC >> 8) ^ wCRC16a[bTmp & 0x0F]) ^ wCRC16b[(bTmp >> 4) & 0x0F];
}
return Standard_Integer (aCRC & HASH_MASK /* myMask */);
}
//=======================================================================
//function : AddString
//purpose : Add or find a string in the hash table
//=======================================================================
const char * LDOM_MemManager::HashTable::AddString
(const char * theString,
const Standard_Integer theLen,
Standard_Integer& theHashIndex)
{
const char * aResult = NULL;
if (theString == NULL) return NULL;
Standard_Integer aHashIndex = Hash (theString, theLen);
TableItem * aNode = &myTable[aHashIndex];
if (aNode -> str == NULL) {
LDOM_HashValue * anAlloc = (LDOM_HashValue *)
myManager.Allocate (theLen + 1 + sizeof(LDOM_HashValue));
anAlloc[0] = LDOM_HashValue (aHashIndex);
aNode -> str = (char *) &anAlloc[1];
memcpy (aNode -> str, theString, theLen);
aNode -> str [theLen] = '\0';
aResult = aNode -> str;
}else{
if (compareStrings (aNode -> str, theString, theLen))
aResult = aNode -> str;
else
while (aNode -> next) {
aNode = aNode -> next;
if (compareStrings (aNode -> str, theString, theLen)) {
aResult = aNode -> str;
break;
}
}
if (aResult == NULL) {
// Attention!!! We can make this allocation in a separate pool
// improving performance
aNode -> next = (TableItem *) myManager.Allocate (sizeof(TableItem));
aNode = aNode -> next;
LDOM_HashValue * anAlloc = (LDOM_HashValue *)
myManager.Allocate (theLen + 1 + sizeof(LDOM_HashValue));
anAlloc[0] = LDOM_HashValue (aHashIndex);
aNode -> str = (char *) &anAlloc[1];
memcpy (aNode -> str, theString, theLen);
aNode -> str [theLen] = '\0';
aResult = aNode -> str;
aNode -> next = NULL;
}
}
theHashIndex = aHashIndex;
return aResult;
}
//=======================================================================
//function : LDOM_MemManager
//purpose : Constructor
//=======================================================================
LDOM_MemManager::LDOM_MemManager (const Standard_Integer aBlockSize)
: myRootElement (NULL),
myFirstBlock (NULL),
myFirstWithoutRoom (NULL),
myBlockSize (convertBlockSize(aBlockSize)),
myHashTable (NULL) {}
//=======================================================================
//function : ~LDOM_MemManager
//purpose : Destructor
//=======================================================================
LDOM_MemManager::~LDOM_MemManager ()
{
#ifdef OCCT_DEBUG
Standard_Integer aSomme = 0, aCount = 0;
MemBlock * aBlock = myFirstBlock;
//FILE * out = fopen ("/tmp/dump","w");
while (aBlock) {
aCount ++;
aSomme += aBlock -> mySize;
// for (const Standard_Integer * aPtr = aBlock -> myBlock;
// aPtr < aBlock -> myEndBlock; ) {
// const char * aStr = (const char *) aPtr;
// Standard_Integer aLen = strlen (aStr) + 1;
// if (aLen > 1) fprintf (out, "%s\n", aStr);
// aPtr += convertBlockSize (aLen);
// }
aBlock = aBlock -> Next();
}
if (aCount > 1)
std::cout << ".. Destroying " << aCount << " LDOM memory allocations: "
<< aSomme / 256 << " kB" << std::endl;
//fclose (out);
#endif
delete myFirstBlock;
if (myHashTable)
delete myHashTable;
}
//=======================================================================
//function : Allocate
//purpose :
//=======================================================================
void * LDOM_MemManager::Allocate (const Standard_Integer theSize)
{
void * aResult = NULL;
Standard_Integer aSize = convertBlockSize (theSize);
if (aSize >= myBlockSize) {
myFirstBlock = new MemBlock (aSize, myFirstBlock);
aResult = myFirstBlock -> Allocate (aSize);
}else{
MemBlock * aBlock = myFirstBlock;
if (aBlock == NULL) {
myFirstBlock = new MemBlock (myBlockSize, myFirstBlock);
return myFirstBlock -> Allocate (aSize);
}
aResult = aBlock -> Allocate (aSize);
if (aResult)
return aResult;
aBlock = aBlock -> Next();
const MemBlock * aFirstWithoutRoom = NULL;
while (aBlock != myFirstWithoutRoom) {
aResult = aBlock -> AllocateAndCheck (aSize, aFirstWithoutRoom);
if (aResult) break;
aBlock = aBlock -> Next();
}
myFirstWithoutRoom = (MemBlock *&)aFirstWithoutRoom;
if (aResult == NULL) {
myFirstBlock = new MemBlock (myBlockSize, myFirstBlock);
aResult = myFirstBlock -> Allocate (aSize);
}
}
return aResult;
}
//=======================================================================
//function : HashedAllocate
//purpose : Memory allocation with access via hash table. No new allocation
// if already present
//=======================================================================
const char * LDOM_MemManager::HashedAllocate (const char * theString,
const Standard_Integer theLen,
Standard_Integer& theHash)
{
if (myHashTable == NULL) myHashTable = new HashTable (* this);
return myHashTable -> AddString (theString, theLen, theHash);
}
//=======================================================================
//function : HashedAllocate
//purpose : Memory allocation with access via hash table. No new allocation
// if already present
//=======================================================================
void LDOM_MemManager::HashedAllocate (const char * aString,
const Standard_Integer theLen,
LDOMBasicString& theResult)
{
theResult.myType = LDOMBasicString::LDOM_AsciiHashed;
Standard_Integer aDummy;
const char * aHashedString = HashedAllocate (aString, theLen, aDummy);
if (aHashedString != NULL)
theResult.myVal.ptr = (void *) aHashedString;
}
//=======================================================================
//function : CompareStrings
//purpose : Compare
//=======================================================================
Standard_Boolean LDOM_MemManager::CompareStrings
(const char * theString,
const Standard_Integer theHashValue,
const char * theHashedStr)
{
if (((LDOM_HashValue *)theHashedStr)[-1] == LDOM_HashValue(theHashValue))
if (!strcmp (theString, theHashedStr))
return Standard_True;
return Standard_False;
}