/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ // dtoa doesn't provide a header file so this simple one was created. #ifndef HERMES_DTOA_DTOA_H #define HERMES_DTOA_DTOA_H #ifdef __cplusplus extern "C" { #endif /// dtoa functions need to allocate memory and that job is handled by the dtoa /// allocator. \c dtoa_alloc is an opaque struct representing the allocator. It /// is created by calling \c dtoa_alloc_init() with a pointer to a memory /// buffer declared with \c DECL_DTOA_ALLOC_MEM(name, size). /// /// The allocator metadata itself is placed in that memory buffer and the rest /// of it is used to satisfy memory allocations. If it is not enough, additional /// allocations are made in the regular heap with malloc()/free(). So, the /// larger the buffer declared by \c DECL_DTOA_ALLOC_MEM(), the less probability /// there that a heap allocation will be needed. /// /// The allocator is not thread safe, so we must guarantee that it is used only /// by one thread a time. Usually we just create it on the stack (which is very /// fast), but it could live in other places, as long as the single thread /// requirement is satisfied. /// /// The allocator metadata itself is less than 128 bytes - the rest is the /// "allocation buffer". The dtoa documentation states that 2304 byte allocation /// buffer is sufficient for most cases except the unusual ones, and a 7400 byte /// allocation buffer is sufficient for all cases. /// /// We don't need to avoid heap allocation at all costs, so we have chosen a /// total allocator size of 1200 bytes, which seems to avoid heap allocations /// for "normal" cases. typedef struct dtoa_alloc dtoa_alloc; /// The minimal size of the dtoa allocator memory buffer. The metadata is less /// than 128 bytes and the rest is available to satisfy dtoa allocations. #define DTOA_ALLOC_MIN_SIZE 256 /// The default size of the dtoa allocator memory buffer, which we use when /// declaring it on the stack. The value attempts to find balance between /// excessive stack consumption and avoiding allocations for "normal" cases. #define DTOA_ALLOC_DEFAULT_SIZE 1200 /// This macro is used to declare a memory buffer for the dtoa allocator. Most /// of all it ensures that the memory is properly aligned. The variable declared /// by this macro is then passed to \c dtoa_alloc_init(). #define DECL_DTOA_ALLOC_MEM(name, bytelen) \ union { \ void *p; \ double d; \ long long l; \ char mem[(bytelen)]; \ } name /// Initialize an allocator using the specified memory buffer, and return a /// pointer to the allocator. Note that this does not stipulate that the /// returned pointer will equal \c mem. dtoa_alloc *dtoa_alloc_init(void *mem, int bytelen); /// Destroy the previously initialized allocator. Primarily, this call frees /// any heap allocations in the allocator. void dtoa_alloc_done(dtoa_alloc *dalloc); /// Converts double into ascii string. /// \param dd the double to convert. /// \param mode the rounding mode, 0 for default.