From 36003b6bb3ba7c03ae46e418d4d25c8fdc40ff4e Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Thu, 1 Jul 2021 00:13:31 +0200 Subject: [PATCH] * Add support for extented variable for M_[F]PRINT * Update documentation * Add test. --- README.md | 18 ++++++++++-------- example/ex11-algo02.c | 16 +++++++--------- m-core.h | 24 ++++++++++++++++++++---- tests/test-mlist.c | 14 ++++++++++++++ 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 47035a50..61379c2a 100644 --- a/README.md +++ b/README.md @@ -5868,13 +5868,17 @@ Return the printf format associated to the type of 'x'. ##### M\_PRINT\_ARG(x) -Print using printf the variable 'x'. The format of 'x' is deduced provided that it is a standard numerical C type. -If m-string is included, it supports also the type 'string\_t'. +Print using printf the variable 'x'. + +The format of 'x' is deduced provided that it is a standard numerical C type. +If m-string is included, it supports also the type 'string\_t' natively. +If the argument is extended (i.e. in the format '(var, optype)' with optype being either an oplist or a type +with a globally registered oplist), then it will call the OUT\_STR method of the oplist on the variable 'var'. ##### M\_FPRINT\_ARG(file, x) -Print into a file 'file' using fprintf the variable 'x'. The format of 'x' is deduced provided that it is a standard numerical C type. -If m-string is included, it supports also the type 'string\_t'. +Print into a file 'file' using fprintf the variable 'x'. +See M\_PRINT\_ARG for details on the supported variable. ##### M\_GET\_STRING\_ARG(string,x,append) @@ -5887,14 +5891,12 @@ It supports also the type 'string\_t'. ##### M\_PRINT(args...) Print using printf all the variable in 'args'. -The format of the arguments are deduced provided that it is a standard numerical C type. -If m-string is included, it supports also the type 'string\_t'. +See M\_PRINT\_ARG for details on the supported variable. ##### M\_FPRINT(file, args...) Print into a file 'file' using fprintf all the variables in 'args'. -The format of the arguments are deduced provided that it is a standard numerical C type. -If m-string is included, it supports also the type 'string\_t'. +See M\_PRINT\_ARG for details on the supported variable. ##### M\_AS\_TYPE(type, x) diff --git a/example/ex11-algo02.c b/example/ex11-algo02.c index af6cc08e..95861f56 100644 --- a/example/ex11-algo02.c +++ b/example/ex11-algo02.c @@ -5,20 +5,21 @@ #include "m-serial-json.h" #include "m-string.h" -/* Define the employee */ +/* Define the employee class */ TUPLE_DEF2(employee, (name, string_t), (age, int), (idnum, int)) +/* Register globaly the employee_t oplist */ #define M_OPL_employee_t() TUPLE_OPLIST(employee, STRING_OPLIST, M_DEFAULT_OPLIST, M_DEFAULT_OPLIST) -/* Define an array of employee and some algorithms on it */ +/* Define an array of employee, register the oplist and define further algorithms on it */ ARRAY_DEF(vector_employee, employee_t) #define M_OPL_vector_employee_t() ARRAY_OPLIST(vector_employee, M_OPL_employee_t()) ALGO_DEF(vector_employee, vector_employee_t) -/* Define the function object to select the sort order - * named 'compare_by' which is an instance of the interface +/* Define the function object to select the sort order. + * It is named 'compare_by' and is an instance of the interface * 'vector_employee_cmp_obj' created by ALGO_DEF. */ FUNC_OBJ_INS_DEF(compare_by /* name of the instance */, @@ -75,15 +76,12 @@ int main(void) // Sort the database by employee ID number M_LET( (cmp, STRING_CTE("idnum")), compare_by_t ) vector_employee_sort_fo(emps, compare_by_as_interface(cmp)); - printf("Employees sorted by idnum are: "); - vector_employee_out_str(stdout, emps); + M_PRINT("Employees sorted by idnum are: ", (emps, vector_employee_t), "\n" ); // Sort the database by employee name M_LET( (cmp, STRING_CTE("name")), compare_by_t ) vector_employee_sort_fo(emps, compare_by_as_interface(cmp)); - printf("\nEmployees sorted by name are: "); - vector_employee_out_str(stdout, emps); - printf("\n"); + M_PRINT("Employees sorted by name are: ", (emps, vector_employee_t), "\n" ); // End } diff --git a/m-core.h b/m-core.h index 60dccd6d..e9e114ef 100644 --- a/m-core.h +++ b/m-core.h @@ -2005,11 +2005,27 @@ m_core_fopen(const char filename[], const char opt[]) /* Can be overloaded by m-string to support string output too */ #define M_CORE_PRINTF_ARG(x) x -/* Print a C variable if it is a standard type to stdout.*/ -#define M_PRINT_ARG(x) printf(M_PRINTF_FORMAT(x), M_CORE_PRINTF_ARG(x) ) +/* Print a C variable if it is a standard type (or extension) to stdout + If a variable is extended (i.e. like (x, type) ) it will use the + method associated to the OUT_STR operator. +*/ +#define M_PRINT_ARG(x) \ + M_IF(M_PARENTHESIS_P(x)) \ + ( M_FPRINT_ARG_OUT_STR(stdout, M_PAIR_2 x, M_PAIR_1 x), \ + printf(M_PRINTF_FORMAT(x), M_CORE_PRINTF_ARG(x) ) ) -/* Print a C variable if it is a standard type to the given file 'f'.*/ -#define M_FPRINT_ARG(f, x) fprintf(f, M_PRINTF_FORMAT(x), M_CORE_PRINTF_ARG(x)) +/* Print a C variable if it is a standard type to the given file 'f'. + If a variable is extended (i.e. like (x, type) ) it will use the + method associated to the OUT_STR operator. +*/ +#define M_FPRINT_ARG(f, x) \ + M_IF(M_PARENTHESIS_P(x)) \ + ( M_FPRINT_ARG_OUT_STR(f, M_PAIR_2 x, M_PAIR_1 x), \ + fprintf(f, M_PRINTF_FORMAT(x), M_CORE_PRINTF_ARG(x) ) ) + +/* Internal macro to call the OUT_STR method */ +#define M_FPRINT_ARG_OUT_STR(file, oplist, var) \ + M_CALL_OUT_STR( M_GLOBAL_OPLIST(oplist) , file, var) /* Get a C variable if it is a standard type from the given file 'f'.*/ #define M_FSCAN_ARG(xptr, f) \ diff --git a/tests/test-mlist.c b/tests/test-mlist.c index 8c8f7b24..216adb10 100644 --- a/tests/test-mlist.c +++ b/tests/test-mlist.c @@ -271,6 +271,20 @@ static void test_mpz(void) assert (list_mpz_equal_p (v, list2)); list_mpz_clear(list2); + // Print using M_FPRINT + f = m_core_fopen ("a-mlist.dat", "wt"); + if (!f) abort(); + M_FPRINT(f, (v, LIST_OPLIST(list_mpz, TESTOBJ_OPLIST)) ); + fclose (f); + + list_mpz_init(list2); + f = m_core_fopen ("a-mlist.dat", "rt"); + b = list_mpz_in_str (list2, f); + assert (b == true); + fclose(f); + assert (list_mpz_equal_p (v, list2)); + list_mpz_clear(list2); + list_mpz_clean(v); list_mpz_init(list2); M_LET(str, STRING_OPLIST) {