/**
 * @file custom_alloc.h
 * @brief Memory allocator declarations
 * @author Iaroslav Makarchuk (i.makarchuk@samsung.com)
 * @date Created Oct 3, 2016
 * @par In Samsung Ukraine R&D Center (SURC) under a contract between
 * @par LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine) and
 * @par "Samsung Elecrtronics Co", Ltd (Seoul, Republic of Korea)
 * @par Copyright: (c) Samsung Electronics Co, Ltd 2015. All rights reserved.
 *
 * This software is proprietary of Samsung Electronics.
 * No part of this software, either material or conceptual may be copied
 * or distributed, transmitted, transcribed, stored in a retrieval system
 * or translated into any human or computer language in any form by any means,
 * electronic, mechanical, manual or otherwise, or disclosed to third parties
 * without the express written permission of Samsung Electronics.
 */

#ifndef CUSTOM_ALLOC_H_
#define CUSTOM_ALLOC_H_

#include <stddef.h>

#define MALLOC_ALIGN		sizeof(size_t)
#define MALLOC_ALIGN_TYPE	size_t
#define MEMMNGR_INIT_MIN_SIZE	0x1000
#define MEMMNGR_INIT_MAX_SIZE	0x10000000

#define MALLOC_MIN_ALLOC_SIZE (sizeof(RBNode) - sizeof(size_t))

typedef enum Color {RED = 0, BLACK = 1} Color;

typedef struct RBNode RBNode;

struct RBNode {
  size_t key;
  RBNode *parent;
  RBNode *left;
  RBNode *right;
  RBNode *next;
  Color color;
};

typedef struct RBTree RBTree;

struct RBTree {
  RBNode *root;
  RBNode tempnode;
};

typedef struct header{
  void *p;
  size_t size;
} Header;

typedef struct memmngr{
  void *end_ptr;
  void *beg_ptr;
  Header *fh;
  RBTree tree;
  void *bp;
  int mngr_initialized;
} Memmngr;

/**
 * @brief Allocates memory of requested size in scope of provided memory manager
 *
 * @param[in]      mngr   A pointer to memory manager, where the memory should
 *                        be allocated
 * @param[in]      size   The requested size of memory to be allocated
 *
 * @retval Returns an address of allocated memory or NULL if allocation failed
 */
void *custom_malloc(Memmngr *mngr, size_t size);

/**
 * @brief Reallocates memory to the requested size in scope of provided memory
 * manager
 *
 * @param[in]      mngr   A pointer to memory manager, where the memory should
 *                        be reallocated
 * @param[in]      addr   The address to be reallocated
 * @param[in]      size   The requested size of memory to be realloc'd
 *
 * @retval Returns an address of reallocated memory or NULL if allocation failed
 */
void *custom_realloc(Memmngr *mngr, void *addr, size_t size);

/**
 * @brief Frees allocated memory
 *
 * @param[in]      mngr   A pointer to memory manager, where the memory should
 *                        be freed
 * @param[in]      addr   The address of memory to be freed
 */
void custom_free(Memmngr *mngr, void *addr);

/**
 * @brief Memory manager initialization
 *
 * @note This functiona should be called before any other usage of memory
 * manager
 *
 * @param[in]      mngr   A pointer to memory manager, which should be
 *                        initialized
 * @param[in]      start  A pointer to the start of memory region, where memory
 *                        manager will allocate the memory
 * @param[in]      size   The size of memory manager's memory region
 *
 * @retval Returns non-zero on success, 0 otherwise.
 */
int custom_alloc_init(Memmngr *mngr, void *start, size_t size);

/**
 * @brief Checks whether the given address belongs to specified memory manager
 *
 * @param[in]      mngr   A pointer to memory manager, where the address should
 *                        be checked
 * @param[in]      ptr    The address to be checked.
 *
 * @retval Returns non-zero if the addre, 0 otherwise.
 */
int custom_is_ptr_in_range(Memmngr *mngr, const void *ptr);

#endif /* CUSTOM_ALLOC_H_ */
