/**
 * @file Format.h
 * @author apio (cloudapio.eu)
 * @brief C-style string formatting.
 *
 * @copyright Copyright (c) 2022-2023, the Luna authors.
 *
 */

#pragma once
#include <luna/Attributes.h>
#include <luna/Result.h>
#include <stdarg.h>

/**
 * @brief The callback type for cstyle_format.
 *
 * The first parameter is the resulting character, and the second one is the arbitrary argument passed to cstyle_format.
 * Functions of this callback type can return errors, which will be propagated by cstyle_format.
 */
typedef Result<void> (*FormatCallback)(char, void*);

/**
 * @brief Create a formatted string.
 *
 * Since this function uses a callback, it is very flexible; it can format output to a buffer, file, or whatever else is
 * needed by the caller.
 *
 * This function lacks floating-point support, and wide character support, but otherwise, it has almost all C printf
 * features: width, precision, alignment, size modifiers, and many more...
 *
 * This function is used to implemented all printf-related functions in Luna's libc and is the most tested component in
 * libluna (see TestFormat.cpp, which tests it through String::format).
 *
 * @param format The C-style format string.
 * @param callback The function to be called for every character in the resulting string.
 * @param arg An arbitrary argument to pass to the callback function.
 * @param ap The variadic argument list.
 * @return Result<usize> An error, or the number of characters in the resulting string.
 */
Result<usize> cstyle_format(const char* format, FormatCallback callback, void* arg, va_list ap);

/**
 * @brief Format a string into a fixed-size buffer.
 *
 * @param buf The buffer to store the resulting string into.
 * @param max The maximum number of bytes to store in the buffer.
 * @param format The format string.
 * @param ap The variadic argument list.
 * @return usize The number of characters in the formatted string. If it is more than or equal to max, the string was
 * truncated.
 */
usize vstring_format(char* buf, usize max, const char* format, va_list ap);

/**
 * @brief Format a string into a fixed-size buffer.
 *
 * @param buf The buffer to store the resulting string into.
 * @param max The maximum number of bytes to store in the buffer.
 * @param format The format string.
 * @param ... The format arguments.
 * @return usize The number of characters in the formatted string. If it is more than or equal to max, the string was
 * truncated.
 */
usize string_format(char* buf, usize max, const char* format, ...) _format(3, 4);