/*
 * Copyright (c) 2024 EdgeImpulse Inc.
 *
 * Generated by Edge Impulse and licensed under the applicable Edge Impulse
 * Terms of Service. Community and Professional Terms of Service
 * (https://edgeimpulse.com/legal/terms-of-service) or Enterprise Terms of
 * Service (https://edgeimpulse.com/legal/enterprise-terms-of-service),
 * according to your product plan subscription (the “License”).
 *
 * This software, documentation and other associated files (collectively referred
 * to as the “Software”) is a single SDK variation generated by the Edge Impulse
 * platform and requires an active paid Edge Impulse subscription to use this
 * Software for any purpose.
 *
 * You may NOT use this Software unless you have an active Edge Impulse subscription
 * that meets the eligibility requirements for the applicable License, subject to
 * your full and continued compliance with the terms and conditions of the License,
 * including without limitation any usage restrictions under the applicable License.
 *
 * If you do not have an active Edge Impulse product plan subscription, or if use
 * of this Software exceeds the usage limitations of your Edge Impulse product plan
 * subscription, you are not permitted to use this Software and must immediately
 * delete and erase all copies of this Software within your control or possession.
 * Edge Impulse reserves all rights and remedies available to enforce its rights.
 *
 * Unless required by applicable law or agreed to in writing, the Software 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, disclaimers and limitations under the License.
 */
#ifndef __EI_ALLOC__H__
#define __EI_ALLOC__H__

#include "memory.hpp"

#if EIDSP_TRACK_ALLOCATIONS
#include <map>
#endif

namespace ei {

template <class T>
struct EiAlloc
{
    typedef T value_type;
    EiAlloc() = default;
    template <class U>
    constexpr EiAlloc(const EiAlloc<U> &) noexcept {}

    T *allocate(size_t n)
    {
        auto bytes = n * sizeof(T);
        auto ptr = ei_dsp_malloc(bytes);
#if EIDSP_TRACK_ALLOCATIONS
        get_allocs()[ptr] = bytes;
#endif
        return (T *)ptr;
    }

    void deallocate(T *p, size_t n) noexcept
    {
#if EIDSP_TRACK_ALLOCATIONS
        auto size_p = get_allocs().find(p);
        ei_dsp_free(p,size_p->second);
        get_allocs().erase(size_p);
#else
        ei_dsp_free(p,0);
#endif
    }
#if EIDSP_TRACK_ALLOCATIONS
    private:
    // [address] -> size requested
    typedef std::map<void*,size_t> map_t;
    static map_t& get_allocs() {
        static map_t allocs;
        return allocs;
    }
#endif
};

template <class T, class U>
bool operator==(const EiAlloc<T> &, const EiAlloc<U> &) { return true; }
template <class T, class U>
bool operator!=(const EiAlloc<T> &, const EiAlloc<U> &) { return false; }
}

#endif //!__EI_ALLOC__H__
