src/core/alloc_func.hpp
branchNewGRF_ports
changeset 6872 1c4a4a609f85
child 6878 7d1ff2f621c7
equal deleted inserted replaced
6871:5a9dc001e1ad 6872:1c4a4a609f85
       
     1 /* $Id$ */
       
     2 
       
     3 /** @file alloc_func.hpp Functions related to the allocation of memory */
       
     4 
       
     5 #ifndef ALLOC_FUNC_HPP
       
     6 #define ALLOC_FUNC_HPP
       
     7 
       
     8 /**
       
     9  * Simplified allocation function that allocates the specified number of
       
    10  * elements of the given type. It also explicitly casts it to the requested
       
    11  * type.
       
    12  * @note throws an error when there is no memory anymore.
       
    13  * @note the memory contains garbage data (i.e. possibly non-zero values).
       
    14  * @param T the type of the variable(s) to allocation.
       
    15  * @param num_elements the number of elements to allocate of the given type.
       
    16  * @return NULL when num_elements == 0, non-NULL otherwise.
       
    17  */
       
    18 template <typename T> FORCEINLINE T* MallocT(size_t num_elements)
       
    19 {
       
    20 	/*
       
    21 	 * MorphOS cannot handle 0 elements allocations, or rather that always
       
    22 	 * returns NULL. So we do that for *all* allocations, thus causing it
       
    23 	 * to behave the same on all OSes.
       
    24 	 */
       
    25 	if (num_elements == 0) return NULL;
       
    26 
       
    27 	T *t_ptr = (T*)malloc(num_elements * sizeof(T));
       
    28 	if (t_ptr == NULL) error("Out of memory. Cannot allocate %i bytes", num_elements * sizeof(T));
       
    29 	return t_ptr;
       
    30 }
       
    31 
       
    32 /**
       
    33  * Simplified allocation function that allocates the specified number of
       
    34  * elements of the given type. It also explicitly casts it to the requested
       
    35  * type.
       
    36  * @note throws an error when there is no memory anymore.
       
    37  * @note the memory contains all zero values.
       
    38  * @param T the type of the variable(s) to allocation.
       
    39  * @param num_elements the number of elements to allocate of the given type.
       
    40  * @return NULL when num_elements == 0, non-NULL otherwise.
       
    41  */
       
    42 template <typename T> FORCEINLINE T* CallocT(size_t num_elements)
       
    43 {
       
    44 	/*
       
    45 	 * MorphOS cannot handle 0 elements allocations, or rather that always
       
    46 	 * returns NULL. So we do that for *all* allocations, thus causing it
       
    47 	 * to behave the same on all OSes.
       
    48 	 */
       
    49 	if (num_elements == 0) return NULL;
       
    50 
       
    51 	T *t_ptr = (T*)calloc(num_elements, sizeof(T));
       
    52 	if (t_ptr == NULL) error("Out of memory. Cannot allocate %i bytes", num_elements * sizeof(T));
       
    53 	return t_ptr;
       
    54 }
       
    55 
       
    56 /**
       
    57  * Simplified reallocation function that allocates the specified number of
       
    58  * elements of the given type. It also explicitly casts it to the requested
       
    59  * type. It extends/shrinks the memory allocation given in t_ptr.
       
    60  * @note throws an error when there is no memory anymore.
       
    61  * @note the memory contains all zero values.
       
    62  * @param T the type of the variable(s) to allocation.
       
    63  * @param t_ptr the previous allocation to extend/shrink.
       
    64  * @param num_elements the number of elements to allocate of the given type.
       
    65  * @return NULL when num_elements == 0, non-NULL otherwise.
       
    66  */
       
    67 template <typename T> FORCEINLINE T* ReallocT(T *t_ptr, size_t num_elements)
       
    68 {
       
    69 	/*
       
    70 	 * MorphOS cannot handle 0 elements allocations, or rather that always
       
    71 	 * returns NULL. So we do that for *all* allocations, thus causing it
       
    72 	 * to behave the same on all OSes.
       
    73 	 */
       
    74 	if (num_elements == 0) {
       
    75 		free(t_ptr);
       
    76 		return NULL;
       
    77 	}
       
    78 
       
    79 	t_ptr = (T*)realloc(t_ptr, num_elements * sizeof(T));
       
    80 	if (t_ptr == NULL) error("Out of memory. Cannot reallocate %i bytes", num_elements * sizeof(T));
       
    81 	return t_ptr;
       
    82 }
       
    83 
       
    84 /**
       
    85  * A small 'wrapper' for allocations that can be done on most OSes on the
       
    86  * stack, but are just too large to fit in the stack on devices with a small
       
    87  * stack such as the NDS.
       
    88  * So when it is possible a stack allocation is made, otherwise a heap
       
    89  * allocation is made and this is freed once the struct goes out of scope.
       
    90  * @param T      the type to make the allocation for
       
    91  * @param length the amount of items to allocate
       
    92  */
       
    93 template <typename T, size_t length>
       
    94 struct SmallStackSafeStackAlloc {
       
    95 #if !defined(__NDS__)
       
    96 	/** Storing the data on the stack */
       
    97 	T data[length];
       
    98 #else
       
    99 	/** Storing it on the heap */
       
   100 	T *data;
       
   101 
       
   102 	/** Allocating the memory */
       
   103 	SmallStackSafeStackAlloc() : data(MallocT<T>(length)) {}
       
   104 	/** And freeing when it goes out of scope */
       
   105 	~SmallStackSafeStackAlloc() { free(data); }
       
   106 #endif
       
   107 
       
   108 	/**
       
   109 	 * Gets a pointer to the data stored in this wrapper.
       
   110 	 * @return the pointer.
       
   111 	 */
       
   112 	operator T* () { return data; }
       
   113 };
       
   114 
       
   115 #endif /* ALLOC_FUNC_HPP */