// SPDX-License-Identifier: GPL-3.0-or-later WITH STruCpp-runtime-exception // Copyright (C) 2025 Autonomy / OpenPLC Project // This file is part of the STruC++ Runtime Library and is covered by the // STruC++ Runtime Library Exception. See COPYING.RUNTIME for details. /** * STruC++ Runtime - IEC Dynamic Memory Allocation * * Implements CODESYS-compatible __NEW/__DELETE operators for dynamic memory. * Uses malloc/free with placement new for allocation to match IEC semantics: * - Returns nullptr (0) on failure (no exceptions) * - __DELETE sets pointer to nullptr after freeing * - Array allocation constructs each element */ #pragma once #include #include #include #include "iec_ptr.hpp" namespace strucpp { /** * Allocate and construct a single object of type T. * Returns nullptr on allocation failure. */ template T* iec_new() { void* mem = std::malloc(sizeof(T)); if (!mem) return nullptr; return new (mem) T(); // Placement new for construction } /** * Allocate and construct an array of count elements of type T. * Returns nullptr on allocation failure. */ template T* iec_new_array(std::size_t count) { if (count == 0) return nullptr; void* mem = std::malloc(sizeof(T) * count); if (!mem) return nullptr; T* arr = static_cast(mem); for (std::size_t i = 0; i < count; ++i) { new (&arr[i]) T(); // Construct each element } return arr; } /** * Deallocate a single object. Sets pointer to nullptr after freeing. * Safe to call with nullptr (no-op). */ template void iec_delete(T*& ptr) { if (ptr) { ptr->~T(); // Call destructor std::free(ptr); ptr = nullptr; } } /** * Deallocate via IEC_Ptr. Extracts raw pointer, frees, and resets to nullptr. */ template void iec_delete(IEC_Ptr& ptr) { T* raw = ptr.get(); if (raw) { raw->~T(); std::free(raw); ptr = nullptr; } } /** * Deallocate an array of objects. Sets pointer to nullptr after freeing. * Note: For simplicity, this uses the same iec_delete since we don't * track array sizes. The destructor for individual elements is trivial * for IEC elementary types. */ template void iec_delete_array(T*& ptr, std::size_t count) { if (ptr) { for (std::size_t i = 0; i < count; ++i) { ptr[i].~T(); } std::free(ptr); ptr = nullptr; } } } // namespace strucpp