<commit_before>// File:      NCollection_IncAllocator.cxx
// Created:   12.04.02 21:16:26
// Author:    <NAME>
// Copyright: Open Cascade 2002

#include <NCollection_IncAllocator.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_Map.hxx>
#include <Standard_Mutex.hxx>
#include <Standard_OutOfMemory.hxx>
#include <stdio.h>

#if defined(_MSC_VER)
# define FMT_SZ_Q "I"
#elif defined(__GNUC__)
# define FMT_SZ_Q "z"
#elif defined(_OCC64)
# define FMT_SZ_Q "l"
#else
# define FMT_SZ_Q ""
#endif

IMPLEMENT_STANDARD_HANDLE  (NCollection_IncAllocator,NCollection_BaseAllocator)
IMPLEMENT_STANDARD_RTTIEXT (NCollection_IncAllocator,NCollection_BaseAllocator)

#define IMEM_SIZE(_size) ((((_size) - 1)/sizeof(aligned_t)) + 1)
#define IMEM_FREE(p_bl) ((unsigned int)(p_bl->p_end_block - p_bl->p_free_space))
#define IMEM_ALIGN(_addr) (sizeof(aligned_t)* IMEM_SIZE((unsigned long)(_addr)))

#define MaxLookup 16

static Standard_Boolean IS_DEBUG = Standard_False;

//=======================================================================
/**
 * Static data map (address -> AllocatorID)
 */
//=======================================================================
static NCollection_DataMap<Standard_Address, Standard_Size>& StorageIDMap()
{
  static NCollection_DataMap<Standard_Address, Standard_Size> TheMap;
  return TheMap;
}

//=======================================================================
/**
 * Static map (AllocatorID)
 */
//=======================================================================
static NCollection_Map<Standard_Size>& StorageIDSet()
{
  static NCollection_Map<Standard_Size> TheMap;
  return TheMap;
}

//=======================================================================
//function : IncAllocator_SetDebugFlag
//purpose  : Turn on/off debugging of memory allocation
//=======================================================================

Standard_EXPORT void IncAllocator_SetDebugFlag(const Standard_Boolean theDebug)
{
  IS_DEBUG = theDebug;
}

//=======================================================================
/**
 * Static value of the current allocation ID. It provides unique
 * numbering of allocators.
 */
//=======================================================================
#ifdef DEBUG
static Standard_Size CurrentID = 0;
static Standard_Size CATCH_ID = 0;

//=======================================================================
//function : Debug_Create
//purpose  : Store the allocator address in the internal maps
//=======================================================================
static void Debug_Create(Standard_Address theAlloc)
{
  static Standard_Mutex aMutex;
  Standard_Boolean isReentrant = Standard::IsReentrant();
  if (isReentrant)
    aMutex.Lock();
  StorageIDMap().Bind(theAlloc, ++CurrentID);
  StorageIDSet().Add(CurrentID);
  if (isReentrant)
    aMutex.Unlock();
  if (CurrentID == CATCH_ID)
  {
    // Place for break point for creation of investigated allocator
    int a = 1;
  }
}

//=======================================================================
//function : Debug_Destroy
//purpose  : Forget the allocator address from the internal maps
//=======================================================================
static void Debug_Destroy(Standard_Address theAlloc)
{
  static Standard_Mutex aMutex;
  Standard_Boolean isReentrant = Standard::IsReentrant();
  if (isReentrant)
    aMutex.Lock();
  if (StorageIDMap().IsBound(theAlloc))
  {
    Standard_Size anID = StorageIDMap()(theAlloc);
    StorageIDSet().Remove(anID);
    StorageIDMap().UnBind(theAlloc);
  }
  if (isReentrant)
    aMutex.Unlock();
}
#endif
//=======================================================================
//function : IncAllocator_PrintAlive
//purpose  : Outputs the alive numbers to the file inc_alive.d
//=======================================================================

Standard_EXPORT void IncAllocator_PrintAlive()
{
  if (!StorageIDSet().IsEmpty())
  {
    FILE * ff = fopen("inc_alive.d", "wt");
    if (ff == NULL)
    {
      cout << "failure writing file inc_alive.d" << endl;
    }
    else
    {
      fprintf(ff, "Alive IncAllocators (number, size in Kb)\n");
      NCollection_DataMap<Standard_Address, Standard_Size>::Iterator
        itMap(StorageIDMap());
      Standard_Size aTotSize = 0;
      Standard_Integer nbAlloc = 0;
      for (; itMap.More(); itMap.Next())
      {
        NCollection_IncAllocator* anAlloc =
          static_cast<NCollection_IncAllocator*>(itMap.Key());
        Standard_Size anID = itMap.Value();
        Standard_Size aSize = anAlloc->GetMemSize();
        aTotSize += aSize;
        nbAlloc++;
        fprintf(ff, "%-8"FMT_SZ_Q"u %8.1f\n", anID, double(aSize)/1024);
      }
      fprintf(ff, "Total:\n%-8d %8.1f\n", nbAlloc, double(aTotSize)/1024);
      fclose(ff);
    }
  }
}

//=======================================================================
//function : NCollection_IncAllocator()
//purpose  : Constructor
//=======================================================================

NCollection_IncAllocator::NCollection_IncAllocator (const size_t theBlockSize)
{
#ifdef ALLOC_TRACK_USAGE
  printf ("\n..NCollection_IncAllocator: Created (%x)\n",this);
#endif
#ifdef DEB
  if (IS_DEBUG)
    Debug_Create(this);
#endif
  const size_t aSize = IMEM_SIZE(sizeof(IBlock)) +
      IMEM_SIZE((theBlockSize > 2*sizeof(IBlock)) ? theBlockSize : 24600);
  IBlock * const aBlock = (IBlock *) malloc (aSize * sizeof(aligned_t));
  myFirstBlock = aBlock;
  mySize = aSize;
  myMemSize = aSize * sizeof(aligned_t);
  if (aBlock == NULL)
    Standard_OutOfMemory::Raise("NCollection_IncAllocator: out of memory");
  aBlock -> p_free_space = (aligned_t *) IMEM_ALIGN (&aBlock[1]);
  aBlock -> p_end_block  = ((aligned_t *) aBlock) + aSize;
  aBlock -> p_next       = NULL;
}

//=======================================================================
//function : ~NCollection_IncAllocator
//purpose  : Destructor
//=======================================================================

NCollection_IncAllocator::~NCollection_IncAllocator ()
{
#ifdef DEB
  if (IS_DEBUG)
    Debug_Destroy(this);
#endif
  Clean();
  free (myFirstBlock);
}

//=======================================================================
//function : Allocate
//purpose  : allocate a memory
//remark   : returns NULL if allocation fails
//=======================================================================

void * NCollection_IncAllocator::Allocate (const size_t aSize)
{
  aligned_t * aResult = NULL;
  const size_t cSize = aSize ? IMEM_SIZE(aSize) : 0;

  if (cSize > mySize) {
    /* If the requested size exceeds normal allocation size, allocate
       a separate block and place it as the head of the list              */
    aResult = (aligned_t *) allocateNewBlock (cSize+1);
    if (aResult)
      myFirstBlock -> p_free_space = myFirstBlock -> p_end_block;
  } else
    if (cSize <= IMEM_FREE(myFirstBlock)) {
      /* If the requested size fits into the free space in the 1st block  */
      aResult = myFirstBlock -> allocateInBlock (cSize);
    } else {
      /* Search for a block in the list with enough free space            */
      int aMaxLookup = MaxLookup;   /* limit the number of blocks to query */
      IBlock * aCurrentBlock = myFirstBlock -> p_next;
      while (aCurrentBlock && aMaxLookup--) {
        if (cSize <= IMEM_FREE(aCurrentBlock)) {
          aResult = aCurrentBlock -> allocateInBlock (cSize);
          break;
        }
        aCurrentBlock = aCurrentBlock -> p_next;
      }
      if (aResult == NULL) {
        /* There is no available block with enough free space. Create a new
           one and place it in the head of the list                       */
        aResult = (aligned_t *) allocateNewBlock (mySize);
        if (aResult)
          myFirstBlock -> p_free_space = aResult + cSize;
      }
    }
  return aResult;
}

//=======================================================================
//function : Reallocate
//purpose  : 
//=======================================================================

void * NCollection_IncAllocator::Reallocate (void         * theAddress,
                                             const size_t oldSize,
                                             const size_t newSize)
{
// Check that the dummy parameters are OK
  if (theAddress == NULL || oldSize == 0)
    return Allocate (newSize);
  const size_t cOldSize = IMEM_SIZE(oldSize);
  const size_t cNewSize = newSize ? IMEM_SIZE(newSize) : 0;
  aligned_t * anAddress = (aligned_t *) theAddress;

// We check only the LAST allocation to do the real extension/contraction
  if (anAddress + cOldSize == myFirstBlock -> p_free_space) {
    myFirstBlock -> p_free_space = anAddress;
// If the new size fits into the memory block => OK
// This also includes any case of contraction
    if (cNewSize <= IMEM_FREE(myFirstBlock)) {
      myFirstBlock -> p_free_space += cNewSize;
      return anAddress;
    }
  }
// In case of contraction of non-terminating allocation, do nothing
  else if (cOldSize >= cNewSize)
    return anAddress;
// Extension of non-terminated allocation if there is enough room in the
// current memory block 
  if (cNewSize <= IMEM_FREE(myFirstBlock)) {
    aligned_t * aResult = myFirstBlock -> allocateInBlock (cNewSize);
    if (aResult)
      for (unsigned i = 0; i < cOldSize; i++)
        aResult[i] = anAddress[i];
    return aResult;
  }

// This is either of the cases:
//   - extension of non-terminating allocation, or
//   - extension of terminating allocation when the new size is too big
// In both cases create a new memory block, allocate memory and copy there
// the reallocated memory.
  aligned_t * aResult = (aligned_t *) allocateNewBlock (mySize);
  if (aResult) {
    myFirstBlock -> p_free_space = aResult + cNewSize;
    for (unsigned i = 0; i < cOldSize; i++)
      aResult[i] = anAddress[i];
  }
  return aResult;
}

//=======================================================================
//function : Free
//purpose  : 
//=======================================================================

void NCollection_IncAllocator::Free (void *)
{}

//=======================================================================
//function : Clean
//purpose  : 
//=======================================================================

void NCollection_IncAllocator::Clean ()
{
#ifdef ALLOC_TRACK_USAGE
  printf ("\n..NCollection_IncAllocator: Memory size to clean:%8.1f kB (%x)\n",
           double(GetMemSize())/1024, this);
#endif
  IBlock * aBlock = myFirstBlock;
  if (aBlock) {
    aBlock -> p_free_space = (aligned_t *) &aBlock[1];
    aBlock = aBlock -> p_next;
    while (aBlock) {
      IBlock * aNext = aBlock -> p_next;
      free (aBlock);
      aBlock = aNext;
    }
    myFirstBlock -> p_next = NULL;
  }
  myMemSize = 0;
}

//=======================================================================
//function : Reset
//purpose  : 
//=======================================================================

void NCollection_IncAllocator::Reset (const Standard_Boolean doReleaseMem)
{
  if (doReleaseMem)
    Clean();
  else {
    Standard_Integer aBlockCount(0);
    IBlock * aBlock = myFirstBlock;
    while (aBlock)
      if (aBlockCount++ < MaxLookup) {
        aBlock -> p_free_space = (aligned_t *) &aBlock[1];
        if (aBlockCount < MaxLookup)
          aBlock = aBlock -> p_next;
        else {
          IBlock * aNext = aBlock -> p_next;
          aBlock -> p_next = NULL;
          aBlock = aNext;
        }
      } else {
        IBlock * aNext = aBlock -> p_next;
        myMemSize -= (aBlock -> p_end_block - (aligned_t *) aBlock) * sizeof (aligned_t);
        free (aBlock);
        aBlock = aNext;
      }
  }
}

//=======================================================================
//function : GetMemSize
//purpose  : diagnostic utility
//=======================================================================

size_t NCollection_IncAllocator::GetMemSize () const
{
//   size_t aResult = 0;
//   IBlock * aBlock = myFirstBlock;
//   while (aBlock) {
//     aResult += (aBlock -> p_end_block - (aligned_t *) aBlock);
//     aBlock = aBlock -> p_next;
//   }
//   return aResult * sizeof (aligned_t);
  return myMemSize;
}

//=======================================================================
//function : allocateNewBlock
//purpose  : 
//=======================================================================

void * NCollection_IncAllocator::allocateNewBlock (const size_t cSize)
{
  aligned_t * aResult = 0L;
  const size_t aSz = cSize + IMEM_SIZE(sizeof(IBlock));
  IBlock * aBlock = (IBlock *) malloc (aSz * sizeof(aligned_t));
  if (aBlock) {
    aBlock -> p_end_block  = ((aligned_t *)aBlock) + aSz;
    aBlock -> p_next = myFirstBlock;
    myFirstBlock = aBlock;
    aResult = (aligned_t *) IMEM_ALIGN(&aBlock[1]);
    myMemSize += aSz * sizeof(aligned_t);
  }
  else
    Standard_OutOfMemory::Raise("NCollection_IncAllocator: out of memory");
  return aResult;
}
<commit_msg>Replaced #ifdef DEBUG introduced in 89ada85 with #ifdef _DEBUG<commit_after>// File:      NCollection_IncAllocator.cxx
// Created:   12.04.02 21:16:26
// Author:    <NAME>
// Copyright: Open Cascade 2002

#include <NCollection_IncAllocator.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_Map.hxx>
#include <Standard_Mutex.hxx>
#include <Standard_OutOfMemory.hxx>
#include <stdio.h>

#if defined(_MSC_VER)
# define FMT_SZ_Q "I"
#elif defined(__GNUC__)
# define FMT_SZ_Q "z"
#elif defined(_OCC64)
# define FMT_SZ_Q "l"
#else
# define FMT_SZ_Q ""
#endif

IMPLEMENT_STANDARD_HANDLE  (NCollection_IncAllocator,NCollection_BaseAllocator)
IMPLEMENT_STANDARD_RTTIEXT (NCollection_IncAllocator,NCollection_BaseAllocator)

#define IMEM_SIZE(_size) ((((_size) - 1)/sizeof(aligned_t)) + 1)
#define IMEM_FREE(p_bl) ((unsigned int)(p_bl->p_end_block - p_bl->p_free_space))
#define IMEM_ALIGN(_addr) (sizeof(aligned_t)* IMEM_SIZE((unsigned long)(_addr)))

#define MaxLookup 16

static Standard_Boolean IS_DEBUG = Standard_False;

//=======================================================================
/**
 * Static data map (address -> AllocatorID)
 */
//=======================================================================
static NCollection_DataMap<Standard_Address, Standard_Size>& StorageIDMap()
{
  static NCollection_DataMap<Standard_Address, Standard_Size> TheMap;
  return TheMap;
}

//=======================================================================
/**
 * Static map (AllocatorID)
 */
//=======================================================================
static NCollection_Map<Standard_Size>& StorageIDSet()
{
  static NCollection_Map<Standard_Size> TheMap;
  return TheMap;
}

//=======================================================================
//function : IncAllocator_SetDebugFlag
//purpose  : Turn on/off debugging of memory allocation
//=======================================================================

Standard_EXPORT void IncAllocator_SetDebugFlag(const Standard_Boolean theDebug)
{
  IS_DEBUG = theDebug;
}

//=======================================================================
/**
 * Static value of the current allocation ID. It provides unique
 * numbering of allocators.
 */
//=======================================================================
#ifdef _DEBUG
static Standard_Size CurrentID = 0;
static Standard_Size CATCH_ID = 0;

//=======================================================================
//function : Debug_Create
//purpose  : Store the allocator address in the internal maps
//=======================================================================
static void Debug_Create(Standard_Address theAlloc)
{
  static Standard_Mutex aMutex;
  Standard_Boolean isReentrant = Standard::IsReentrant();
  if (isReentrant)
    aMutex.Lock();
  StorageIDMap().Bind(theAlloc, ++CurrentID);
  StorageIDSet().Add(CurrentID);
  if (isReentrant)
    aMutex.Unlock();
  if (CurrentID == CATCH_ID)
  {
    // Place for break point for creation of investigated allocator
    int a = 1;
  }
}

//=======================================================================
//function : Debug_Destroy
//purpose  : Forget the allocator address from the internal maps
//=======================================================================
static void Debug_Destroy(Standard_Address theAlloc)
{
  static Standard_Mutex aMutex;
  Standard_Boolean isReentrant = Standard::IsReentrant();
  if (isReentrant)
    aMutex.Lock();
  if (StorageIDMap().IsBound(theAlloc))
  {
    Standard_Size anID = StorageIDMap()(theAlloc);
    StorageIDSet().Remove(anID);
    StorageIDMap().UnBind(theAlloc);
  }
  if (isReentrant)
    aMutex.Unlock();
}
#endif
//=======================================================================
//function : IncAllocator_PrintAlive
//purpose  : Outputs the alive numbers to the file inc_alive.d
//=======================================================================

Standard_EXPORT void IncAllocator_PrintAlive()
{
  if (!StorageIDSet().IsEmpty())
  {
    FILE * ff = fopen("inc_alive.d", "wt");
    if (ff == NULL)
    {
      cout << "failure writing file inc_alive.d" << endl;
    }
    else
    {
      fprintf(ff, "Alive IncAllocators (number, size in Kb)\n");
      NCollection_DataMap<Standard_Address, Standard_Size>::Iterator
        itMap(StorageIDMap());
      Standard_Size aTotSize = 0;
      Standard_Integer nbAlloc = 0;
      for (; itMap.More(); itMap.Next())
      {
        NCollection_IncAllocator* anAlloc =
          static_cast<NCollection_IncAllocator*>(itMap.Key());
        Standard_Size anID = itMap.Value();
        Standard_Size aSize = anAlloc->GetMemSize();
        aTotSize += aSize;
        nbAlloc++;
        fprintf(ff, "%-8"FMT_SZ_Q"u %8.1f\n", anID, double(aSize)/1024);
      }
      fprintf(ff, "Total:\n%-8d %8.1f\n", nbAlloc, double(aTotSize)/1024);
      fclose(ff);
    }
  }
}

//=======================================================================
//function : NCollection_IncAllocator()
//purpose  : Constructor
//=======================================================================

NCollection_IncAllocator::NCollection_IncAllocator (const size_t theBlockSize)
{
#ifdef ALLOC_TRACK_USAGE
  printf ("\n..NCollection_IncAllocator: Created (%x)\n",this);
#endif
#ifdef DEB
  if (IS_DEBUG)
    Debug_Create(this);
#endif
  const size_t aSize = IMEM_SIZE(sizeof(IBlock)) +
      IMEM_SIZE((theBlockSize > 2*sizeof(IBlock)) ? theBlockSize : 24600);
  IBlock * const aBlock = (IBlock *) malloc (aSize * sizeof(aligned_t));
  myFirstBlock = aBlock;
  mySize = aSize;
  myMemSize = aSize * sizeof(aligned_t);
  if (aBlock == NULL)
    Standard_OutOfMemory::Raise("NCollection_IncAllocator: out of memory");
  aBlock -> p_free_space = (aligned_t *) IMEM_ALIGN (&aBlock[1]);
  aBlock -> p_end_block  = ((aligned_t *) aBlock) + aSize;
  aBlock -> p_next       = NULL;
}

//=======================================================================
//function : ~NCollection_IncAllocator
//purpose  : Destructor
//=======================================================================

NCollection_IncAllocator::~NCollection_IncAllocator ()
{
#ifdef DEB
  if (IS_DEBUG)
    Debug_Destroy(this);
#endif
  Clean();
  free (myFirstBlock);
}

//=======================================================================
//function : Allocate
//purpose  : allocate a memory
//remark   : returns NULL if allocation fails
//=======================================================================

void * NCollection_IncAllocator::Allocate (const size_t aSize)
{
  aligned_t * aResult = NULL;
  const size_t cSize = aSize ? IMEM_SIZE(aSize) : 0;

  if (cSize > mySize) {
    /* If the requested size exceeds normal allocation size, allocate
       a separate block and place it as the head of the list              */
    aResult = (aligned_t *) allocateNewBlock (cSize+1);
    if (aResult)
      myFirstBlock -> p_free_space = myFirstBlock -> p_end_block;
  } else
    if (cSize <= IMEM_FREE(myFirstBlock)) {
      /* If the requested size fits into the free space in the 1st block  */
      aResult = myFirstBlock -> allocateInBlock (cSize);
    } else {
      /* Search for a block in the list with enough free space            */
      int aMaxLookup = MaxLookup;   /* limit the number of blocks to query */
      IBlock * aCurrentBlock = myFirstBlock -> p_next;
      while (aCurrentBlock && aMaxLookup--) {
        if (cSize <= IMEM_FREE(aCurrentBlock)) {
          aResult = aCurrentBlock -> allocateInBlock (cSize);
          break;
        }
        aCurrentBlock = aCurrentBlock -> p_next;
      }
      if (aResult == NULL) {
        /* There is no available block with enough free space. Create a new
           one and place it in the head of the list                       */
        aResult = (aligned_t *) allocateNewBlock (mySize);
        if (aResult)
          myFirstBlock -> p_free_space = aResult + cSize;
      }
    }
  return aResult;
}

//=======================================================================
//function : Reallocate
//purpose  : 
//=======================================================================

void * NCollection_IncAllocator::Reallocate (void         * theAddress,
                                             const size_t oldSize,
                                             const size_t newSize)
{
// Check that the dummy parameters are OK
  if (theAddress == NULL || oldSize == 0)
    return Allocate (newSize);
  const size_t cOldSize = IMEM_SIZE(oldSize);
  const size_t cNewSize = newSize ? IMEM_SIZE(newSize) : 0;
  aligned_t * anAddress = (aligned_t *) theAddress;

// We check only the LAST allocation to do the real extension/contraction
  if (anAddress + cOldSize == myFirstBlock -> p_free_space) {
    myFirstBlock -> p_free_space = anAddress;
// If the new size fits into the memory block => OK
// This also includes any case of contraction
    if (cNewSize <= IMEM_FREE(myFirstBlock)) {
      myFirstBlock -> p_free_space += cNewSize;
      return anAddress;
    }
  }
// In case of contraction of non-terminating allocation, do nothing
  else if (cOldSize >= cNewSize)
    return anAddress;
// Extension of non-terminated allocation if there is enough room in the
// current memory block 
  if (cNewSize <= IMEM_FREE(myFirstBlock)) {
    aligned_t * aResult = myFirstBlock -> allocateInBlock (cNewSize);
    if (aResult)
      for (unsigned i = 0; i < cOldSize; i++)
        aResult[i] = anAddress[i];
    return aResult;
  }

// This is either of the cases:
//   - extension of non-terminating allocation, or
//   - extension of terminating allocation when the new size is too big
// In both cases create a new memory block, allocate memory and copy there
// the reallocated memory.
  aligned_t * aResult = (aligned_t *) allocateNewBlock (mySize);
  if (aResult) {
    myFirstBlock -> p_free_space = aResult + cNewSize;
    for (unsigned i = 0; i < cOldSize; i++)
      aResult[i] = anAddress[i];
  }
  return aResult;
}

//=======================================================================
//function : Free
//purpose  : 
//=======================================================================

void NCollection_IncAllocator::Free (void *)
{}

//=======================================================================
//function : Clean
//purpose  : 
//=======================================================================

void NCollection_IncAllocator::Clean ()
{
#ifdef ALLOC_TRACK_USAGE
  printf ("\n..NCollection_IncAllocator: Memory size to clean:%8.1f kB (%x)\n",
           double(GetMemSize())/1024, this);
#endif
  IBlock * aBlock = myFirstBlock;
  if (aBlock) {
    aBlock -> p_free_space = (aligned_t *) &aBlock[1];
    aBlock = aBlock -> p_next;
    while (aBlock) {
      IBlock * aNext = aBlock -> p_next;
      free (aBlock);
      aBlock = aNext;
    }
    myFirstBlock -> p_next = NULL;
  }
  myMemSize = 0;
}

//=======================================================================
//function : Reset
//purpose  : 
//=======================================================================

void NCollection_IncAllocator::Reset (const Standard_Boolean doReleaseMem)
{
  if (doReleaseMem)
    Clean();
  else {
    Standard_Integer aBlockCount(0);
    IBlock * aBlock = myFirstBlock;
    while (aBlock)
      if (aBlockCount++ < MaxLookup) {
        aBlock -> p_free_space = (aligned_t *) &aBlock[1];
        if (aBlockCount < MaxLookup)
          aBlock = aBlock -> p_next;
        else {
          IBlock * aNext = aBlock -> p_next;
          aBlock -> p_next = NULL;
          aBlock = aNext;
        }
      } else {
        IBlock * aNext = aBlock -> p_next;
        myMemSize -= (aBlock -> p_end_block - (aligned_t *) aBlock) * sizeof (aligned_t);
        free (aBlock);
        aBlock = aNext;
      }
  }
}

//=======================================================================
//function : GetMemSize
//purpose  : diagnostic utility
//=======================================================================

size_t NCollection_IncAllocator::GetMemSize () const
{
//   size_t aResult = 0;
//   IBlock * aBlock = myFirstBlock;
//   while (aBlock) {
//     aResult += (aBlock -> p_end_block - (aligned_t *) aBlock);
//     aBlock = aBlock -> p_next;
//   }
//   return aResult * sizeof (aligned_t);
  return myMemSize;
}

//=======================================================================
//function : allocateNewBlock
//purpose  : 
//=======================================================================

void * NCollection_IncAllocator::allocateNewBlock (const size_t cSize)
{
  aligned_t * aResult = 0L;
  const size_t aSz = cSize + IMEM_SIZE(sizeof(IBlock));
  IBlock * aBlock = (IBlock *) malloc (aSz * sizeof(aligned_t));
  if (aBlock) {
    aBlock -> p_end_block  = ((aligned_t *)aBlock) + aSz;
    aBlock -> p_next = myFirstBlock;
    myFirstBlock = aBlock;
    aResult = (aligned_t *) IMEM_ALIGN(&aBlock[1]);
    myMemSize += aSz * sizeof(aligned_t);
  }
  else
    Standard_OutOfMemory::Raise("NCollection_IncAllocator: out of memory");
  return aResult;
}

{'fraction_non_alphanumeric': 0.27234465870829505, 'fraction_numerical': 0.0053565962656871744, 'mean_word_length': 3.9737392959086586, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 103, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6021095', 'n_tokens_mistral': 7770, 'n_tokens_neox': 7313, 'n_words': 1814}