text: /*
   *
   *    Copyright (c) 2020 Project CHIP Authors
   *    All rights reserved.
   *
   *    Licensed under the Apache License, Version 2.0 (the "License");
   *    you may not use this file except in compliance with the License.
   *    You may obtain a copy of the License at
   *
   *        http://www.apache.org/licenses/LICENSE-2.0
   *
   *    Unless required by applicable law or agreed to in writing, software
   *    distributed under the License is distributed on an "AS IS" BASIS,
   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *    See the License for the specific language governing permissions and
   *    limitations under the License.
   */
  
  /**
   *    @file
   *      This file defines heap memory allocation APIs for CHIP.
   *
   */
  
  #pragma once
  
  #include <core/CHIPError.h>
  #include <stdlib.h>
  
  #include <new>
  #include <utility>
  
  namespace chip {
  namespace Platform {
  
  #define CHIP_ZERO_AT(value)                                                                                                        \
      do                                                                                                                             \
      {                                                                                                                              \
          memset(&value, 0, sizeof(value));                                                                                          \
      } while (0)
  
  /**
   * This function is called by CHIP layer to initialize memory and resources
   * required for proper functionality of the CHIP memory allocator.
   * This function is platform specific and might be empty in certain cases.
   * For example, this function is doing nothing when the C Standard Library malloc()
   * and free() functions are used for memory allocation.
   *
   * @param[in]  buf      A pointer to a dedicated memory buffer, which should be used as
   *                      a memory pool for CHIP memory allocation.
   *                      This input is optional (defaults to NULL) and shouldn't be used
   *                      if a dedicated memory buffer is not used.
   *
   * @param[in]  bufSize  Size of a dedicated memory buffer. This input is optional (defaults to 0)
   *                      and shouldn't be used if dedicated memory buffer is not used.
   *                      When a dedicated memory buffer is used the function checks and
   *                      generates an error if buffer size is not big enough to support
   *                      CHIP use cases.
   *
   * @retval  #CHIP_ERROR_BUFFER_TOO_SMALL  If dedicated input buffer size is not sufficient
   *                                         to support CHIP use cases.
   * @retval  #CHIP_NO_ERROR                On success.
   * @retval  other                          An error generated by platform-specific memory
   *                                         initialization function.
   *
   */
  extern CHIP_ERROR MemoryInit(void * buf = nullptr, size_t bufSize = 0);
  
  /**
   * This function is called by the CHIP layer to releases all resources that were allocated
   * by MemoryInit() function.
   * This function can be an empty call if there is no need to release resources. For example,
   * this is the case when the C Standard Library malloc() and free() functions are used
   * for memory allocation.
   *
   */
  extern void MemoryShutdown();
  
  /**
   * This function is called by the CHIP layer to allocate a block of memory of "size" bytes.
   *
   * @param[in]  size             Specifies requested memory size in bytes.
   *
   * @param[in]  isLongTermAlloc  A Boolean indicating whether (true) or not (false) the
   *                              requested memory block is for long term use. A long term
   *                              allocation is memory that should stay allocated until secure
   *                              session/handshake is complete. Examples of a long term
   *                              allocation include blocks allocated for CASE/PASE objects
   *                              and their context data. A short term allocation is a memory
   *                              needed to perform specific operation and can be released
   *                              immediately after that. This input helps to optimize memory
   *                              utilization in a memory constrained system. Use of this parameter
   *                              is arbitrary and depends on function implementer. For example,
   *                              this parameter is ignored when the C Standard Library malloc()
   *                              is used.
   *
   * @retval  Pointer to a memory block in case of success.
   * @retval  NULL-pointer if memory allocation fails.
   *
   */
  extern void * MemoryAlloc(size_t size, bool isLongTermAlloc);
  
  /**
   * This function is called by the CHIP layer to allocate a block of memory of "size" bytes.
   *
   * @param[in]  size             Specifies requested memory size in bytes.
   *
   * @retval  Pointer to a memory block in case of success.
   * @retval  NULL-pointer if memory allocation fails.
   *
   */
  extern void * MemoryAlloc(size_t size);
  
  /**
   * This function is called by the CHIP layer to allocate a block of memory for an array of num
   * elements, each of them size bytes long, and initializes all its bits to zero.
   * The effective result is the allocation of a zero-initialized memory block of (num*size) bytes.
   *
   * @param[in]  num              Specifies number of elements to allocate.
   * @param[in]  size             Specifies size of each element in bytes.
   *
   * @retval  Pointer to a memory block in case of success.
   * @retval  NULL-pointer if memory allocation fails.
   *
   */
  extern void * MemoryCalloc(size_t num, size_t size);
  
  /**
   * This function is called by the Chip layer to change the size of the memory block pointed to by p.
   * The function may move the memory block to a new location (whose address is returned by the function).
   * The content of the memory block is preserved up to the lesser of the new and old sizes, even if the
   * block is moved to a new location. If the new size is larger, the value of the newly allocated portion
   * is indeterminate.
  
   * In case that p is a null pointer, the function behaves like malloc, assigning a new block of size bytes
   * and returning a pointer to its beginning.
   *
   * @param[in]  p                Pointer to a memory block previously allocated with MemoryAlloc, MemoryCalloc
   *                              or MemoryRealloc.
   * @param[in]  size             Specifies new size for the memory block, in bytes..
   *
   * @retval  Pointer to a memory block in case of success.
   * @retval  NULL-pointer if memory allocation fails.
   *
   */
  extern void * MemoryRealloc(void * p, size_t size);
  
  /**
   * This function is called by the Chip layer to release a memory block allocated by
   * the MemoryAlloc(), MemoryCalloc or MemoryRealloc.
   * @param[in]  p                Pointer to a memory block that should be released.
   *
   */
  extern void MemoryFree(void * p);
  
  /**
   * This function wraps the operator `new` with placement-new using MemoryAlloc().
   * Instead of
   *    p = new T(arguments)
   * use
   *    p = New<T>(arguments)
   * In a few cases it may be necessary to add explicit casts to arguments, notably
   * when passing integer constants to smaller integer parameters.
   */
  template <typename T, typename... Args>
  inline T * New(Args &&... args)
  {
      return new (MemoryAlloc(sizeof(T))) T(std::forward<Args>(args)...);
  }
  
  /**
   * This function wraps the operator `delete` with using MemoryFree().
   * Instead of
   *    delete p
   * use
   *    Delete(p)
   */
  template <typename T>
  inline void Delete(T * p)
  {
      p->~T();
      MemoryFree(p);
  }
  
  } // namespace Platform
  } // namespace chip
  