// Created on: 2014-04-01
// Created by: Kirill Gavrilov
// Copyright (c) 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.

#ifndef _NCollection_Buffer_HeaderFile
#define _NCollection_Buffer_HeaderFile

#include <NCollection_BaseAllocator.hxx>
#include <Standard_Dump.hxx>
#include <Standard_Transient.hxx>

//! Low-level buffer object.
class NCollection_Buffer : public Standard_Transient
{

public:

  //! Default constructor.
  //! When theData is NULL but theSize is not 0 than buffer of specified size will be allocated.
  //! @param theAlloc memory allocator
  //! @param theSize  buffer size
  //! @param theData  buffer data allocated by theAlloc
  NCollection_Buffer (const Handle(NCollection_BaseAllocator)& theAlloc,
                      const Standard_Size                      theSize = 0,
                      Standard_Byte*                           theData = NULL)
  : myData (NULL),
    mySize (0),
    myAllocator (theAlloc)
  {
    if (theData != NULL)
    {
      myData = theData;
      mySize = theSize;
    }
    else
    {
      Allocate (theSize);
    }
  }

  //! Destructor.
  ~NCollection_Buffer()
  {
    Free();
  }

  //! @return buffer data
  const Standard_Byte* Data() const
  {
    return myData;
  }

  //! @return buffer data
  Standard_Byte* ChangeData()
  {
    return myData;
  }

  //! @return true if buffer is not allocated
  bool IsEmpty() const
  {
    return myData == NULL;
  }

  //! Return buffer length in bytes.
  Standard_Size Size() const
  {
    return mySize;
  }

  //! @return buffer allocator
  const Handle(NCollection_BaseAllocator)& Allocator() const
  {
    return myAllocator;
  }

  //! Assign new buffer allocator with de-allocation of buffer.
  void SetAllocator (const Handle(NCollection_BaseAllocator)& theAlloc)
  {
    Free();
    myAllocator = theAlloc;
  }

  //! Allocate the buffer.
  //! @param theSize buffer length in bytes
  bool Allocate (const Standard_Size theSize)
  {
    Free();
    mySize = theSize;
    if (theSize != 0
    || !myAllocator.IsNull())
    {
      myData = (Standard_Byte* )myAllocator->Allocate (theSize);
    }

    if (myData == NULL)
    {
      mySize = 0;
      return false;
    }
    return true;
  }

  //! De-allocate buffer.
  void Free()
  {
    if (!myAllocator.IsNull())
    {
      myAllocator->Free (myData);
    }
    myData = NULL;
    mySize = 0;
  }

  //! Dumps the content of me into the stream
  virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const
  {
    (void)theDepth;
    OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myData)
    OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySize)
    OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myAllocator.get())
  }

protected:

  Standard_Byte*                    myData;      //!< data pointer
  Standard_Size                     mySize;      //!< buffer length in bytes
  Handle(NCollection_BaseAllocator) myAllocator; //!< buffer allocator

public:

  DEFINE_STANDARD_RTTI_INLINE(NCollection_Buffer,Standard_Transient) // Type definition

};

DEFINE_STANDARD_HANDLE(NCollection_Buffer, Standard_Transient)

#endif // _NCollection_Buffer_HeaderFile
