diff --git a/exec/src/run_ast.c b/exec/src/run_ast.c index a5ab38ab..36a76a12 100644 --- a/exec/src/run_ast.c +++ b/exec/src/run_ast.c @@ -6,7 +6,7 @@ /* By: maiboyer +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/07/11 17:22:29 by maiboyer #+# #+# */ -/* Updated: 2024/07/15 18:40:19 by maiboyer ### ########.fr */ +/* Updated: 2024/07/16 13:27:18 by maiboyer ### ########.fr */ /* */ /* ************************************************************************** */ @@ -95,23 +95,49 @@ t_error _get_expansion_value(t_ast_expansion *self, t_state *state, t_expansion_ return (NO_ERROR); } -t_error _handle_no_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_len_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_assign_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_assign_colon_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_alternate_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_alternate_colon_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_default_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_default_colon_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_error_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_error_colon_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; +#include "me/convert/itoa.h" -t_error _handle_suffix_pattern_smallest_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_suffix_pattern_longest_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_prefix_pattern_smallest_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; -t_error _handle_prefix_pattern_longest_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) NOT_DONE; +t_error _handle_len_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) +{ + t_str len_str; + t_usize len; -t_error _get_op_func(t_ast_expansion *self, t_error (**op_func)()) + if (value->exists && value->str != NULL) + len = str_len(value->str); + else + len = 0; + len_str = me_itoa(len); + mem_free(value->str); + value->exists = true; + value->str = len_str; + return (NO_ERROR); +}; + +t_error _handle_no_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) +{ + (void)(self); + (void)(state); + (void)(value); + if (self == NULL || state == NULL || value == NULL) + return (ERROR); + return (NO_ERROR); +}; + +t_error _handle_assign_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_assign_colon_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_alternate_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_alternate_colon_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_default_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_default_colon_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_error_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_error_colon_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; + +t_error _handle_suffix_pattern_smallest_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_suffix_pattern_longest_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_prefix_pattern_smallest_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; +t_error _handle_prefix_pattern_longest_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) NOT_DONE; + +t_error _get_op_func(t_ast_expansion *self, t_error (**op_func)(t_ast_expansion *self, t_state *state, t_expansion_result *value)) { if (self == NULL || op_func == NULL) return (ERROR); @@ -144,16 +170,17 @@ t_error _get_op_func(t_ast_expansion *self, t_error (**op_func)()) return (ERROR); } -t_error _handle_expansion_operator(t_ast_expansion *self, t_state *state, t_expansion_result *out) +t_error _handle_expansion_operator(t_ast_expansion *self, t_state *state, t_expansion_result *value) { - t_str value; - t_error (*op_func)(); + t_error (*op_func)(t_ast_expansion *self, t_state *state, t_expansion_result *value); - if (self == NULL || state == NULL || out == NULL) + if (self == NULL || state == NULL || value == NULL) return (ERROR); if (_get_op_func(self, &op_func)) return (ERROR); - return (ERROR); + if (op_func(self, state, value)) + return (ERROR); + return (NO_ERROR); } // End Internals funcs @@ -195,21 +222,18 @@ t_error run_word(t_ast_word *word, t_state *state, void *out) NOT_DONE; t_error run_expansion(t_ast_expansion *self, t_state *state, t_expansion_result *out) { t_expansion_result ret; + bool is_special_var; - if (_is_special_var(self)) - { - if (_run_expansion_special_var(self, state, &ret)) - return (ERROR); - } - else - { - if (_get_expansion_value(self, state, &ret)) - return (ERROR); - } + is_special_var = _is_special_var(self); + if (is_special_var && _run_expansion_special_var(self, state, &ret)) + return (ERROR); + if (!is_special_var && _get_expansion_value(self, state, &ret)) + return (ERROR); if (_handle_expansion_operator(self, state, &ret)) return (ERROR); - - return (ERROR); + if (self->len_operator && _handle_len_operator(self, state, &ret)) + return (ERROR); + return (*out = ret, NO_ERROR); } // FUNCTIONS diff --git a/stdme/gen.list b/stdme/gen.list index 7287d70c..cf0ab2a3 100644 --- a/stdme/gen.list +++ b/stdme/gen.list @@ -1,3 +1,7 @@ +convert/i16_to_str +convert/i32_to_str +convert/i64_to_str +convert/i8_to_str convert/str_to_i16 convert/str_to_i16_utils convert/str_to_i32 @@ -14,6 +18,10 @@ convert/str_to_u64 convert/str_to_u64_utils convert/str_to_u8 convert/str_to_u8_utils +convert/u16_to_str +convert/u32_to_str +convert/u64_to_str +convert/u8_to_str vec/buf_str/buf_str vec/buf_str/buf_str_functions2 vec/buf_str/buf_str_functions3 diff --git a/stdme/generic_sources/src/convert/C__PREFIX___to_str.c__TEMPLATE__ b/stdme/generic_sources/src/convert/C__PREFIX___to_str.c__TEMPLATE__ new file mode 100644 index 00000000..fbfacccf --- /dev/null +++ b/stdme/generic_sources/src/convert/C__PREFIX___to_str.c__TEMPLATE__ @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error C__PREFIX___to_str_base_prefix(C__TYPE__ val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.C__FIELD__ = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.C__UFIELD__ = ~value.C__UFIELD__ + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error C__PREFIX___to_str_base(C__TYPE__ val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (C__PREFIX___to_str_base_prefix(val, base, "", out)); +} + +t_error C__PREFIX___to_str(C__TYPE__ val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (C__PREFIX___to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/include/me/convert/numbers_to_str.h b/stdme/include/me/convert/numbers_to_str.h new file mode 100644 index 00000000..54b33fa8 --- /dev/null +++ b/stdme/include/me/convert/numbers_to_str.h @@ -0,0 +1,239 @@ + +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* numbers_to_str.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/16 17:18:47 by maiboyer #+# #+# */ +/* Updated: 2024/07/16 17:19:31 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef NUMBERS_TO_STR_H +#define NUMBERS_TO_STR_H + +#include "me/types.h" + +typedef struct s_num_str t_num_str; +typedef struct s_num_str_state t_num_str_state; + +struct s_num_str +{ + t_u64 value; + bool is_nonnegative; + t_str base; + t_str prefix; +}; + +struct s_num_str_state +{ + bool print; + bool zero; + char buffer[40]; + t_str base; + t_u64 base_len; + t_u64 modulus; + t_u64 value; + t_usize idx; +}; + +union u_nums { + t_u64 u64; + t_i64 i64; + t_u32 u32; + t_i32 i32; + t_u16 u16; + t_i16 i16; + t_u8 u8; + t_i8 i8; + +}; + +/// @brief Convert a signed 8-bit integer to a string with a base and a prefix. +/// @param val The signed 8-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param prefix The prefix to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error i8_to_str_base_prefix(t_i8 val, t_str base, t_str prefix, t_str *out); + +/// @brief Convert a signed 8-bit integer to a string with a base +/// @param val The signed 8-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error i8_to_str_base(t_i8 val, t_str base, t_str *out); + +/// @brief Convert a signed 8-bit integer to a string. +/// @param val The signed 8-bit integer to convert. +/// @param out The output string. +/// @return True in case of error, false otherwise. +t_error i8_to_str(t_i8 val, t_str *out); + +/// @brief Convert a unsigned 8-bit integer to a string with a base and a prefix. +/// @param val The unsigned 8-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param prefix The prefix to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error u8_to_str_base_prefix(t_u8 val, t_str base, t_str prefix, t_str *out); + +/// @brief Convert a unsigned 8-bit integer to a string with a base +/// @param val The unsigned 8-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error u8_to_str_base(t_u8 val, t_str base, t_str *out); + +/// @brief Convert a unsigned 8-bit integer to a string. +/// @param val The unsigned 8-bit integer to convert. +/// @param out The output string. +/// @return True in case of error, false otherwise. +t_error u8_to_str(t_u8 val, t_str *out); + +/// @brief Convert a signed 16-bit integer to a string with a base and a prefix. +/// @param val The signed 16-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param prefix The prefix to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error i16_to_str_base_prefix(t_i16 val, t_str base, t_str prefix, t_str *out); + +/// @brief Convert a signed 16-bit integer to a string with a base +/// @param val The signed 16-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error i16_to_str_base(t_i16 val, t_str base, t_str *out); + +/// @brief Convert a signed 16-bit integer to a string. +/// @param val The signed 16-bit integer to convert. +/// @param out The output string. +/// @return True in case of error, false otherwise. +t_error i16_to_str(t_i16 val, t_str *out); + +/// @brief Convert a unsigned 16-bit integer to a string with a base and a prefix. +/// @param val The unsigned 16-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param prefix The prefix to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error u16_to_str_base_prefix(t_u16 val, t_str base, t_str prefix, t_str *out); + +/// @brief Convert a unsigned 16-bit integer to a string with a base +/// @param val The unsigned 16-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error u16_to_str_base(t_u16 val, t_str base, t_str *out); + +/// @brief Convert a unsigned 16-bit integer to a string. +/// @param val The unsigned 16-bit integer to convert. +/// @param out The output string. +/// @return True in case of error, false otherwise. +t_error u16_to_str(t_u16 val, t_str *out); + +/// @brief Convert a signed 32-bit integer to a string with a base and a prefix. +/// @param val The signed 32-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param prefix The prefix to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error i32_to_str_base_prefix(t_i32 val, t_str base, t_str prefix, t_str *out); + +/// @brief Convert a signed 32-bit integer to a string with a base +/// @param val The signed 32-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error i32_to_str_base(t_i32 val, t_str base, t_str *out); + +/// @brief Convert a signed 32-bit integer to a string. +/// @param val The signed 32-bit integer to convert. +/// @param out The output string. +/// @return True in case of error, false otherwise. +t_error i32_to_str(t_i32 val, t_str *out); + +/// @brief Convert a unsigned 32-bit integer to a string with a base and a prefix. +/// @param val The unsigned 32-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param prefix The prefix to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error u32_to_str_base_prefix(t_u32 val, t_str base, t_str prefix, t_str *out); + +/// @brief Convert a unsigned 32-bit integer to a string with a base +/// @param val The unsigned 32-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error u32_to_str_base(t_u32 val, t_str base, t_str *out); + +/// @brief Convert a unsigned 32-bit integer to a string. +/// @param val The unsigned 32-bit integer to convert. +/// @param out The output string. +/// @return True in case of error, false otherwise. +t_error u32_to_str(t_u32 val, t_str *out); + +/// @brief Convert a signed 64-bit integer to a string with a base and a prefix. +/// @param val The signed 64-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param prefix The prefix to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error i64_to_str_base_prefix(t_i64 val, t_str base, t_str prefix, t_str *out); + +/// @brief Convert a signed 64-bit integer to a string with a base +/// @param val The signed 64-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error i64_to_str_base(t_i64 val, t_str base, t_str *out); + +/// @brief Convert a signed 64-bit integer to a string. +/// @param val The signed 64-bit integer to convert. +/// @param out The output string. +/// @return True in case of error, false otherwise. +t_error i64_to_str(t_i64 val, t_str *out); + +/// @brief Convert a unsigned 64-bit integer to a string with a base and a prefix. +/// @param val The unsigned 64-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param prefix The prefix to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error u64_to_str_base_prefix(t_u64 val, t_str base, t_str prefix, t_str *out); + +/// @brief Convert a unsigned 64-bit integer to a string with a base +/// @param val The unsigned 64-bit integer to convert. +/// @param base The base to use for the conversion. +/// @param out The output string. +/// @return True in case of error, false otherwise. +/// @note The base must be a string of at least 2 characters and no duplicates. +t_error u64_to_str_base(t_u64 val, t_str base, t_str *out); + +/// @brief Convert a unsigned 64-bit integer to a string. +/// @param val The unsigned 64-bit integer to convert. +/// @param out The output string. +/// @return True in case of error, false otherwise. +t_error u64_to_str(t_u64 val, t_str *out); + + +#endif /* NUMBERS_TO_STR_H */ diff --git a/stdme/input.toml b/stdme/input.toml index 5a7dff11..fbd6fbf4 100644 --- a/stdme/input.toml +++ b/stdme/input.toml @@ -37,6 +37,79 @@ replace.C__MIN__ = "value" replace.C__ZERO__ = "value" replace.C__SIGNED_TYPE__ = "bool" +[definition.num_to_str] +headers = [] +sources = ["generic_sources/src/convert/C__PREFIX___to_str.c__TEMPLATE__"] +replace.C__TYPE__ = "type" +replace.C__PREFIX__ = "prefix" +replace.C__FIELD__ = "type" +replace.C__UFIELD__ = "type" + + +[[create.num_to_str]] +sources_output = "src/convert/" +headers_output = "" +replace.C__TYPE__ = "t_i64" +replace.C__UFIELD__ = "u64" +replace.C__FIELD__ = "i64" +replace.C__PREFIX__ = "i64" + +[[create.num_to_str]] +sources_output = "src/convert/" +headers_output = "" +replace.C__TYPE__ = "t_u64" +replace.C__UFIELD__ = "u64" +replace.C__FIELD__ = "u64" +replace.C__PREFIX__ = "u64" + +[[create.num_to_str]] +sources_output = "src/convert/" +headers_output = "" +replace.C__TYPE__ = "t_i32" +replace.C__UFIELD__ = "u32" +replace.C__FIELD__ = "i32" +replace.C__PREFIX__ = "i32" + +[[create.num_to_str]] +sources_output = "src/convert/" +headers_output = "" +replace.C__TYPE__ = "t_u32" +replace.C__UFIELD__ = "u32" +replace.C__FIELD__ = "u32" +replace.C__PREFIX__ = "u32" + +[[create.num_to_str]] +sources_output = "src/convert/" +headers_output = "" +replace.C__TYPE__ = "t_i16" +replace.C__UFIELD__ = "u16" +replace.C__FIELD__ = "i16" +replace.C__PREFIX__ = "i16" + +[[create.num_to_str]] +sources_output = "src/convert/" +headers_output = "" +replace.C__TYPE__ = "t_u16" +replace.C__UFIELD__ = "u16" +replace.C__FIELD__ = "u16" +replace.C__PREFIX__ = "u16" + +[[create.num_to_str]] +sources_output = "src/convert/" +headers_output = "" +replace.C__TYPE__ = "t_i8" +replace.C__UFIELD__ = "u8" +replace.C__FIELD__ = "i8" +replace.C__PREFIX__ = "i8" + +[[create.num_to_str]] +sources_output = "src/convert/" +headers_output = "" +replace.C__TYPE__ = "t_u8" +replace.C__UFIELD__ = "u8" +replace.C__FIELD__ = "u8" +replace.C__PREFIX__ = "u8" + [[create.str_to_num]] sources_output = "src/convert/" headers_output = "" diff --git a/stdme/output/src/convert/i16_to_str.c b/stdme/output/src/convert/i16_to_str.c new file mode 100644 index 00000000..0b023d2a --- /dev/null +++ b/stdme/output/src/convert/i16_to_str.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error i16_to_str_base_prefix(t_i16 val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.i16 = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.u16 = ~value.u16 + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error i16_to_str_base(t_i16 val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (i16_to_str_base_prefix(val, base, "", out)); +} + +t_error i16_to_str(t_i16 val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (i16_to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/output/src/convert/i32_to_str.c b/stdme/output/src/convert/i32_to_str.c new file mode 100644 index 00000000..88e0f5fa --- /dev/null +++ b/stdme/output/src/convert/i32_to_str.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error i32_to_str_base_prefix(t_i32 val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.i32 = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.u32 = ~value.u32 + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error i32_to_str_base(t_i32 val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (i32_to_str_base_prefix(val, base, "", out)); +} + +t_error i32_to_str(t_i32 val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (i32_to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/output/src/convert/i64_to_str.c b/stdme/output/src/convert/i64_to_str.c new file mode 100644 index 00000000..066ed270 --- /dev/null +++ b/stdme/output/src/convert/i64_to_str.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error i64_to_str_base_prefix(t_i64 val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.i64 = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.u64 = ~value.u64 + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error i64_to_str_base(t_i64 val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (i64_to_str_base_prefix(val, base, "", out)); +} + +t_error i64_to_str(t_i64 val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (i64_to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/output/src/convert/i8_to_str.c b/stdme/output/src/convert/i8_to_str.c new file mode 100644 index 00000000..c49530b4 --- /dev/null +++ b/stdme/output/src/convert/i8_to_str.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error i8_to_str_base_prefix(t_i8 val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.i8 = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.u8 = ~value.u8 + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error i8_to_str_base(t_i8 val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (i8_to_str_base_prefix(val, base, "", out)); +} + +t_error i8_to_str(t_i8 val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (i8_to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/output/src/convert/u16_to_str.c b/stdme/output/src/convert/u16_to_str.c new file mode 100644 index 00000000..6e345ebf --- /dev/null +++ b/stdme/output/src/convert/u16_to_str.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error u16_to_str_base_prefix(t_u16 val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.u16 = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.u16 = ~value.u16 + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error u16_to_str_base(t_u16 val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (u16_to_str_base_prefix(val, base, "", out)); +} + +t_error u16_to_str(t_u16 val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (u16_to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/output/src/convert/u32_to_str.c b/stdme/output/src/convert/u32_to_str.c new file mode 100644 index 00000000..fe7f2ca2 --- /dev/null +++ b/stdme/output/src/convert/u32_to_str.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error u32_to_str_base_prefix(t_u32 val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.u32 = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.u32 = ~value.u32 + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error u32_to_str_base(t_u32 val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (u32_to_str_base_prefix(val, base, "", out)); +} + +t_error u32_to_str(t_u32 val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (u32_to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/output/src/convert/u64_to_str.c b/stdme/output/src/convert/u64_to_str.c new file mode 100644 index 00000000..e793dd22 --- /dev/null +++ b/stdme/output/src/convert/u64_to_str.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error u64_to_str_base_prefix(t_u64 val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.u64 = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.u64 = ~value.u64 + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error u64_to_str_base(t_u64 val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (u64_to_str_base_prefix(val, base, "", out)); +} + +t_error u64_to_str(t_u64 val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (u64_to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/output/src/convert/u8_to_str.c b/stdme/output/src/convert/u8_to_str.c new file mode 100644 index 00000000..a945130c --- /dev/null +++ b/stdme/output/src/convert/u8_to_str.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* str_to_i64.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/01 21:15:19 by maiboyer #+# #+# */ +/* Updated: 2024/02/01 23:18:52 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/char/char.h" +#include "me/convert/numbers_to_str.h" +#include "me/str/str.h" +#include "me/types.h" + +t_error _format_u64(t_num_str args, t_str *out); + +t_error u8_to_str_base_prefix(t_u8 val, t_str base, t_str prefix, + t_str *out) +{ + union u_nums value; + bool is_nonnegative; + + if (out == NULL || base == NULL || prefix == NULL) + return (ERROR); + value.u8 = val; + is_nonnegative = val < 0; + if (is_nonnegative) + value.u8 = ~value.u8 + 1; + return (_format_u64((t_num_str){.value = value.u64, \ + .is_nonnegative = is_nonnegative, \ + .base = base, \ + .prefix = prefix}, \ + out)); +} + +t_error u8_to_str_base(t_u8 val, t_str base, t_str *out) +{ + if (out == NULL || base == NULL) + return (ERROR); + return (u8_to_str_base_prefix(val, base, "", out)); +} + +t_error u8_to_str(t_u8 val, t_str *out) +{ + if (out == NULL) + return (ERROR); + return (u8_to_str_base_prefix(val, "0123456789", "", out)); +} diff --git a/stdme/output/src/vec/buf_str/buf_str.c b/stdme/output/src/vec/buf_str/buf_str.c index f660e393..a58a43a4 100644 --- a/stdme/output/src/vec/buf_str/buf_str.c +++ b/stdme/output/src/vec/buf_str/buf_str.c @@ -10,11 +10,8 @@ /* */ /* ************************************************************************** */ -#include "me/mem/mem.h" -#include "me/mem/mem.h" #include "me/mem/mem.h" #include "me/types.h" -#include "me/mem/mem.h" #include "me/vec/vec_buf_str.h" #include @@ -45,7 +42,7 @@ t_error vec_buf_str_push(t_vec_buf_str *vec, t_string element) /// Return true in case of an error t_error vec_buf_str_reserve(t_vec_buf_str *vec, t_usize wanted_capacity) { - size_t new_capacity; + size_t new_capacity; if (vec == NULL) return (ERROR); @@ -54,7 +51,8 @@ t_error vec_buf_str_reserve(t_vec_buf_str *vec, t_usize wanted_capacity) new_capacity = (vec->capacity * 3) / 2 + 1; while (wanted_capacity > new_capacity) new_capacity = (new_capacity * 3) / 2 + 1; - vec->buffer = mem_realloc_array(vec->buffer, new_capacity, sizeof(t_string)); + vec->buffer = + mem_realloc_array(vec->buffer, new_capacity, sizeof(t_string)); vec->capacity = new_capacity; } return (NO_ERROR); @@ -83,6 +81,8 @@ t_error vec_buf_str_pop(t_vec_buf_str *vec, t_string *value) /// This function is safe to call with `free_elem` being NULL void vec_buf_str_free(t_vec_buf_str vec) { + if (vec.buffer == NULL) + return; if (vec.free_func) { while (vec.len) diff --git a/stdme/output/src/vec/buf_str/buf_str_functions2.c b/stdme/output/src/vec/buf_str/buf_str_functions2.c index b7f7688f..fd4c6100 100644 --- a/stdme/output/src/vec/buf_str/buf_str_functions2.c +++ b/stdme/output/src/vec/buf_str/buf_str_functions2.c @@ -27,7 +27,7 @@ t_error vec_buf_str_find(t_vec_buf_str *vec, idx = 0; while (idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_string *)&vec->buffer[idx])) { *index = idx; return (NO_ERROR); @@ -48,7 +48,7 @@ t_error vec_buf_str_find_starting(t_vec_buf_str *vec, idx = starting_index; while (idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_string *)&vec->buffer[idx])) { *index = idx; return (NO_ERROR); @@ -69,7 +69,7 @@ t_error vec_buf_str_all(t_vec_buf_str *vec, *result = true; while (*result && idx < vec->len) { - if (!fn(&vec->buffer[idx])) + if (!fn((const t_string *)&vec->buffer[idx])) *result = false; idx++; } @@ -87,7 +87,7 @@ t_error vec_buf_str_any(t_vec_buf_str *vec, *result = false; while (*result && idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_string *)&vec->buffer[idx])) *result = true; idx++; } diff --git a/stdme/output/src/vec/str/str.c b/stdme/output/src/vec/str/str.c index ce288abe..0c2daa9f 100644 --- a/stdme/output/src/vec/str/str.c +++ b/stdme/output/src/vec/str/str.c @@ -10,11 +10,8 @@ /* */ /* ************************************************************************** */ -#include "me/mem/mem.h" -#include "me/mem/mem.h" #include "me/mem/mem.h" #include "me/types.h" -#include "me/mem/mem.h" #include "me/vec/vec_str.h" #include @@ -45,7 +42,7 @@ t_error vec_str_push(t_vec_str *vec, t_str element) /// Return true in case of an error t_error vec_str_reserve(t_vec_str *vec, t_usize wanted_capacity) { - size_t new_capacity; + size_t new_capacity; if (vec == NULL) return (ERROR); @@ -54,7 +51,8 @@ t_error vec_str_reserve(t_vec_str *vec, t_usize wanted_capacity) new_capacity = (vec->capacity * 3) / 2 + 1; while (wanted_capacity > new_capacity) new_capacity = (new_capacity * 3) / 2 + 1; - vec->buffer = mem_realloc_array(vec->buffer, new_capacity, sizeof(t_str)); + vec->buffer = + mem_realloc_array(vec->buffer, new_capacity, sizeof(t_str)); vec->capacity = new_capacity; } return (NO_ERROR); @@ -83,6 +81,8 @@ t_error vec_str_pop(t_vec_str *vec, t_str *value) /// This function is safe to call with `free_elem` being NULL void vec_str_free(t_vec_str vec) { + if (vec.buffer == NULL) + return; if (vec.free_func) { while (vec.len) diff --git a/stdme/output/src/vec/str/str_functions2.c b/stdme/output/src/vec/str/str_functions2.c index cd755f72..af61b8e1 100644 --- a/stdme/output/src/vec/str/str_functions2.c +++ b/stdme/output/src/vec/str/str_functions2.c @@ -27,7 +27,7 @@ t_error vec_str_find(t_vec_str *vec, idx = 0; while (idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_str *)&vec->buffer[idx])) { *index = idx; return (NO_ERROR); @@ -48,7 +48,7 @@ t_error vec_str_find_starting(t_vec_str *vec, idx = starting_index; while (idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_str *)&vec->buffer[idx])) { *index = idx; return (NO_ERROR); @@ -69,7 +69,7 @@ t_error vec_str_all(t_vec_str *vec, *result = true; while (*result && idx < vec->len) { - if (!fn(&vec->buffer[idx])) + if (!fn((const t_str *)&vec->buffer[idx])) *result = false; idx++; } @@ -87,7 +87,7 @@ t_error vec_str_any(t_vec_str *vec, *result = false; while (*result && idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_str *)&vec->buffer[idx])) *result = true; idx++; } diff --git a/stdme/output/src/vec/u8/u8.c b/stdme/output/src/vec/u8/u8.c index d9cfcbbf..1d5529fc 100644 --- a/stdme/output/src/vec/u8/u8.c +++ b/stdme/output/src/vec/u8/u8.c @@ -10,11 +10,8 @@ /* */ /* ************************************************************************** */ -#include "me/mem/mem.h" -#include "me/mem/mem.h" #include "me/mem/mem.h" #include "me/types.h" -#include "me/mem/mem.h" #include "me/vec/vec_u8.h" #include @@ -45,7 +42,7 @@ t_error vec_u8_push(t_vec_u8 *vec, t_u8 element) /// Return true in case of an error t_error vec_u8_reserve(t_vec_u8 *vec, t_usize wanted_capacity) { - size_t new_capacity; + size_t new_capacity; if (vec == NULL) return (ERROR); @@ -54,7 +51,8 @@ t_error vec_u8_reserve(t_vec_u8 *vec, t_usize wanted_capacity) new_capacity = (vec->capacity * 3) / 2 + 1; while (wanted_capacity > new_capacity) new_capacity = (new_capacity * 3) / 2 + 1; - vec->buffer = mem_realloc_array(vec->buffer, new_capacity, sizeof(t_u8)); + vec->buffer = + mem_realloc_array(vec->buffer, new_capacity, sizeof(t_u8)); vec->capacity = new_capacity; } return (NO_ERROR); @@ -83,6 +81,8 @@ t_error vec_u8_pop(t_vec_u8 *vec, t_u8 *value) /// This function is safe to call with `free_elem` being NULL void vec_u8_free(t_vec_u8 vec) { + if (vec.buffer == NULL) + return; if (vec.free_func) { while (vec.len) diff --git a/stdme/output/src/vec/u8/u8_functions2.c b/stdme/output/src/vec/u8/u8_functions2.c index 765fba7e..e5efdd0c 100644 --- a/stdme/output/src/vec/u8/u8_functions2.c +++ b/stdme/output/src/vec/u8/u8_functions2.c @@ -27,7 +27,7 @@ t_error vec_u8_find(t_vec_u8 *vec, idx = 0; while (idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_u8 *)&vec->buffer[idx])) { *index = idx; return (NO_ERROR); @@ -48,7 +48,7 @@ t_error vec_u8_find_starting(t_vec_u8 *vec, idx = starting_index; while (idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_u8 *)&vec->buffer[idx])) { *index = idx; return (NO_ERROR); @@ -69,7 +69,7 @@ t_error vec_u8_all(t_vec_u8 *vec, *result = true; while (*result && idx < vec->len) { - if (!fn(&vec->buffer[idx])) + if (!fn((const t_u8 *)&vec->buffer[idx])) *result = false; idx++; } @@ -87,7 +87,7 @@ t_error vec_u8_any(t_vec_u8 *vec, *result = false; while (*result && idx < vec->len) { - if (fn(&vec->buffer[idx])) + if (fn((const t_u8 *)&vec->buffer[idx])) *result = true; idx++; } diff --git a/stdme/src.list b/stdme/src.list index d0bc717f..d6ee3636 100644 --- a/stdme/src.list +++ b/stdme/src.list @@ -27,6 +27,7 @@ char/tolower char/toupper convert/atoi convert/itoa +convert/numbers_to_str fs/close fs/fs_internal fs/open diff --git a/stdme/src/convert/numbers_to_str.c b/stdme/src/convert/numbers_to_str.c new file mode 100644 index 00000000..3a35500c --- /dev/null +++ b/stdme/src/convert/numbers_to_str.c @@ -0,0 +1,99 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* numbers_to_str.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maiboyer +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/07/16 18:15:57 by maiboyer #+# #+# */ +/* Updated: 2024/07/16 18:19:42 by maiboyer ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "me/convert/numbers_to_str.h" +#include "me/mem/mem.h" +#include "me/str/str.h" +#include "me/types.h" +#include + +static t_error _check_base(t_str base) +{ + t_usize i; + t_usize j; + + i = 0; + if (base == NULL) + return (ERROR); + while (base[i] != '\0') + { + j = 1; + while (base[i + j] != '\0') + if (base[i + (j++)] == base[i]) + return (ERROR); + i++; + } + if (i <= 1) + return (ERROR); + return (NO_ERROR); +} + +static void _set_modulus(t_num_str_state *s) +{ + s->modulus = 0; + s->base_len = str_len(s->base); + while (UINT64_MAX - s->modulus >= s->base_len) + s->modulus += s->base_len; +} + +static char _get_char(t_u64 value, t_num_str_state *s) +{ + if (value == 0) + s->zero = true; + else + s->zero = false; + return (s->base[value]); +} + +static t_error _format_u64_base_innner(t_num_str_state *s) +{ + char c; + + if (s->value == 0) + return (s->buffer[s->idx++] = _get_char(0, s), NO_ERROR); + while (s->modulus) + { + c = _get_char(s->value / s->modulus, s); + if (s->zero || s->print) + { + s->buffer[s->idx++] = c; + s->print = true; + } + s->value = s->value % s->modulus; + s->modulus /= s->base_len; + } + return (NO_ERROR); +} + +t_error _format_u64(t_num_str args, t_str *out) +{ + t_num_str_state s; + t_str res; + + if (_check_base(args.base)) + return (ERROR); + if (args.prefix == NULL) + args.prefix = ""; + mem_set_zero(&s, sizeof(s)); + s.idx = 0; + if (args.is_nonnegative) + s.buffer[s.idx++] = '-'; + _set_modulus(&s); + s.print = false; + if (_format_u64_base_innner(&s)) + return (ERROR); + res = str_join(args.prefix, s.buffer); + if (res == NULL) + return (ERROR); + return (*out = res, NO_ERROR); +} +