Loading CMakeLists.txt +3 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.20) project(rsvp-c-cpp LANGUAGES C CXX) include(CTest) enable_testing() include(FetchContent) FetchContent_Declare( googletest Loading src/rsvp.c +159 −1 Original line number Diff line number Diff line Loading @@ -364,6 +364,164 @@ int rsvp_data_add_vars(rsvp_data_t* data, unsigned int count, ...) return NO_ERROR; } int count_char_in_int(int value) { // Take into account the sign int chars = value < 0 ? 1 : 0; int modulo = 0; if (value == 0) return 1; value = abs(value); while (value > 0) { modulo = value % 10; if (modulo == 0) value /= 10; else value = (value - modulo) / 10; chars++; } return chars; } int count_chars_in_double(double value, int precision) { // Start at precision. Plus one to account for the dot int chars = precision + 1; int int_value = (int)value; // Account for negative 0 if (value > -1.0 && value < 0.0) chars += 1; return count_char_in_int(int_value) + chars; } char* rsvp_data_to_string(rsvp_data_t* data, int double_precision) { char *str = NULL; size_t len = strlen(data->cmd) + 1; char dbl_format[] = "%.5f"; str = (char*)malloc(len); if (!str) { set_error_string("Allocation for command failed"); return NULL; } memset(str, 0, len); memcpy(str, data->cmd, len - 1); for (unsigned int i = 0; i < data->args_count; i++) { rsvp_var_t *arg = data->args[i]; const char *type = rsvp_type_str[arg->type]; char *arg_value = NULL, *arg_name = NULL; size_t value_len = 0, arg_len = 0; int ret = 0; // "; NAME ( INT )=\0" arg_len = 1 + strlen(arg->name) + 1 + strlen(type) + 3; arg_name = (char*)malloc(arg_len); if (snprintf(arg_name, arg_len, ";%s(%s)=", arg->name, type) != (arg_len - 1)) ret = -1; switch (arg->type) { case INT: value_len = count_char_in_int(arg->value.i) + 1; arg_value = (char*)malloc(value_len); if (snprintf(arg_value, value_len, "%d", arg->value.i) != (value_len - 1)) ret = -1; break; case DBL: value_len = count_chars_in_double(arg->value.d, double_precision) + 1; arg_value = (char*)malloc(value_len); if (snprintf(arg_value, value_len, "%.5f", arg->value.d) != (value_len - 1)) ret = -1; break; case BOOL: char *value = arg->value.b > 0 ? "TRUE" : "FALSE"; value_len = strlen(value) + 1; arg_value = (char*)malloc(value_len); if (snprintf(arg_value, value_len, "%s", value) != (value_len - 1)) ret = -1; break; case STR: value_len = strlen(arg->value.s) + 1; arg_value = (char*)malloc(value_len); if (snprintf(arg_value, value_len, "%s", arg->value.s) != value_len - 1) ret = -1; break; case VECD: int index = 0; // [] value_len = 2; for (int i = 0; i < arg_len; i++) { rsvp_vecd_elem_t* elem = rsvp_var_get_vecd_elem(arg->value.vecd, i); // NAME + = + DOUBLE + , or \0 value_len += strlen(elem->name) + 1 + count_chars_in_double(elem->value, double_precision) + 1; } arg_value = (char*)malloc(value_len); memset(arg_value, 0, value_len); arg_value[index++] = '['; for (int i = 0; i < arg_len; i++) { rsvp_vecd_elem_t* elem = rsvp_var_get_vecd_elem(arg->value.vecd, i); size_t dbl_len = count_chars_in_double(elem->value, double_precision) ; char* dbl_val = (char*)malloc(dbl_len + 1); dbl_val = snprintf(dbl_val, dbl_len, dbl_format, elem->value); strcat(arg_value, elem->name); index += strlen(elem->name); arg_value[index++] = '='; } ret = -1; break; case VECS: int index = 0; for (int i = 0; i < arg->len; i++) { value_len += strlen(arg->value.vecs[i]) + 1; } arg_value = (char*)malloc(value_len); memset(arg_value, 0, value_len); for (int i = 0; i < arg->len; i++) { char *str = arg->value.vecs[i]; strcat(arg_value, str); index += strlen(str); arg_value[index++] = '\t'; } arg_value[index-1] = '\0'; break; } if (ret < 0) { //Skip this arg continue; } str = (char*)realloc(str, len + strlen(arg_name) + strlen(arg_value)); str = strcat(str, arg_name); str = strcat(str, arg_value); len = strlen(str) + 1; free(arg_value); free(arg_name); } return str; } void rsvp_var_print(rsvp_var_t *var) { printf("Name: %s, type: %s, value: ", var->name, rsvp_type_str[var->type]); Loading Loading @@ -526,7 +684,7 @@ rsvp_var_t* rsvp_var_create_bool(char *name, int value) rsvp_var_t* rsvp_var_create_string(char *name, char* value) { size_t len = strlen(name) + 1; size_t len = strlen(value) + 1; rsvp_var_t *var = rsvp_var_init(name); if (!var) return NULL; Loading src/rsvp.h +3 −2 Original line number Diff line number Diff line Loading @@ -110,12 +110,13 @@ extern int rsvp_data_add_var(rsvp_data_t* data, rsvp_var_t* var); extern int rsvp_data_add_vars(rsvp_data_t* data, unsigned int count, ...); /** * @brief Convert rsvp_data_t to a string of raw RSVP data * @brief Convert rsvp_data_t to a string of raw RSVP data. Remember to free the returned string * * @param data Data to convert * @param double_precision Number of decimals for for double values * @return char* String of raw RSVP data */ extern char* rsvp_data_to_string(rsvp_data_t* data); extern char* rsvp_data_to_string(rsvp_data_t* data, int double_precision); /** * @brief Print the RSVP data struct to stdout Loading tests/CMakeLists.txt +8 −8 Original line number Diff line number Diff line cmake_minimum_required(VERSION 3.20) project(test) project(tests) set(C_TEST c_test) set(CPP_TEST) enable_testing() add_executable(${C_TEST} rsvp_test.cpp) target_link_libraries(${C_TEST} rsvp GTest::gtest_main) add_executable(${PROJECT_NAME} rsvp_test.cpp ../src/rsvp.c) target_link_libraries(${PROJECT_NAME} rsvp GTest::gtest_main) add_executable(${PROJECT_NAME}pp testpp.cpp) target_link_libraries(${PROJECT_NAME}pp rsvppp) add_executable(${CPP_TEST}pp testpp.cpp) target_link_libraries(${CPP_TEST}pp rsvppp) include(GoogleTest) gtest_discover_tests(${PROJECT_NAME}) No newline at end of file gtest_discover_tests(${C_TEST}) No newline at end of file tests/main.c 0 → 100644 +51 −0 Original line number Diff line number Diff line #include <stdio.h> #include <stdlib.h> int count_char_in_int(int value) { // Take into account the sign int chars = value < 0 ? 1 : 0; int modulo = 0; if (value == 0) return 1; value = abs(value); while (value > 0) { modulo = value % 10; if (modulo == 0) value /= 10; else value = (value - modulo) / 10; chars++; } return chars; } int count_chars_in_double(double value, int precision) { // Start at precision. Plus one to account for the dot int chars = precision + 1; int int_value = (int)value; // Account for negative 0 if (value > -1.0 && value < 0.0) chars += 1; return count_char_in_int(int_value) + chars; } int main() { int val = 11111111; double val1 = -1.87844189641134813; printf("Val: %d, chars: %d\n", val, count_char_in_int(val)); printf("Val: %.5f, chars: %d\n", val1, count_chars_in_double(val1, 5)); return 0; } No newline at end of file Loading
CMakeLists.txt +3 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.20) project(rsvp-c-cpp LANGUAGES C CXX) include(CTest) enable_testing() include(FetchContent) FetchContent_Declare( googletest Loading
src/rsvp.c +159 −1 Original line number Diff line number Diff line Loading @@ -364,6 +364,164 @@ int rsvp_data_add_vars(rsvp_data_t* data, unsigned int count, ...) return NO_ERROR; } int count_char_in_int(int value) { // Take into account the sign int chars = value < 0 ? 1 : 0; int modulo = 0; if (value == 0) return 1; value = abs(value); while (value > 0) { modulo = value % 10; if (modulo == 0) value /= 10; else value = (value - modulo) / 10; chars++; } return chars; } int count_chars_in_double(double value, int precision) { // Start at precision. Plus one to account for the dot int chars = precision + 1; int int_value = (int)value; // Account for negative 0 if (value > -1.0 && value < 0.0) chars += 1; return count_char_in_int(int_value) + chars; } char* rsvp_data_to_string(rsvp_data_t* data, int double_precision) { char *str = NULL; size_t len = strlen(data->cmd) + 1; char dbl_format[] = "%.5f"; str = (char*)malloc(len); if (!str) { set_error_string("Allocation for command failed"); return NULL; } memset(str, 0, len); memcpy(str, data->cmd, len - 1); for (unsigned int i = 0; i < data->args_count; i++) { rsvp_var_t *arg = data->args[i]; const char *type = rsvp_type_str[arg->type]; char *arg_value = NULL, *arg_name = NULL; size_t value_len = 0, arg_len = 0; int ret = 0; // "; NAME ( INT )=\0" arg_len = 1 + strlen(arg->name) + 1 + strlen(type) + 3; arg_name = (char*)malloc(arg_len); if (snprintf(arg_name, arg_len, ";%s(%s)=", arg->name, type) != (arg_len - 1)) ret = -1; switch (arg->type) { case INT: value_len = count_char_in_int(arg->value.i) + 1; arg_value = (char*)malloc(value_len); if (snprintf(arg_value, value_len, "%d", arg->value.i) != (value_len - 1)) ret = -1; break; case DBL: value_len = count_chars_in_double(arg->value.d, double_precision) + 1; arg_value = (char*)malloc(value_len); if (snprintf(arg_value, value_len, "%.5f", arg->value.d) != (value_len - 1)) ret = -1; break; case BOOL: char *value = arg->value.b > 0 ? "TRUE" : "FALSE"; value_len = strlen(value) + 1; arg_value = (char*)malloc(value_len); if (snprintf(arg_value, value_len, "%s", value) != (value_len - 1)) ret = -1; break; case STR: value_len = strlen(arg->value.s) + 1; arg_value = (char*)malloc(value_len); if (snprintf(arg_value, value_len, "%s", arg->value.s) != value_len - 1) ret = -1; break; case VECD: int index = 0; // [] value_len = 2; for (int i = 0; i < arg_len; i++) { rsvp_vecd_elem_t* elem = rsvp_var_get_vecd_elem(arg->value.vecd, i); // NAME + = + DOUBLE + , or \0 value_len += strlen(elem->name) + 1 + count_chars_in_double(elem->value, double_precision) + 1; } arg_value = (char*)malloc(value_len); memset(arg_value, 0, value_len); arg_value[index++] = '['; for (int i = 0; i < arg_len; i++) { rsvp_vecd_elem_t* elem = rsvp_var_get_vecd_elem(arg->value.vecd, i); size_t dbl_len = count_chars_in_double(elem->value, double_precision) ; char* dbl_val = (char*)malloc(dbl_len + 1); dbl_val = snprintf(dbl_val, dbl_len, dbl_format, elem->value); strcat(arg_value, elem->name); index += strlen(elem->name); arg_value[index++] = '='; } ret = -1; break; case VECS: int index = 0; for (int i = 0; i < arg->len; i++) { value_len += strlen(arg->value.vecs[i]) + 1; } arg_value = (char*)malloc(value_len); memset(arg_value, 0, value_len); for (int i = 0; i < arg->len; i++) { char *str = arg->value.vecs[i]; strcat(arg_value, str); index += strlen(str); arg_value[index++] = '\t'; } arg_value[index-1] = '\0'; break; } if (ret < 0) { //Skip this arg continue; } str = (char*)realloc(str, len + strlen(arg_name) + strlen(arg_value)); str = strcat(str, arg_name); str = strcat(str, arg_value); len = strlen(str) + 1; free(arg_value); free(arg_name); } return str; } void rsvp_var_print(rsvp_var_t *var) { printf("Name: %s, type: %s, value: ", var->name, rsvp_type_str[var->type]); Loading Loading @@ -526,7 +684,7 @@ rsvp_var_t* rsvp_var_create_bool(char *name, int value) rsvp_var_t* rsvp_var_create_string(char *name, char* value) { size_t len = strlen(name) + 1; size_t len = strlen(value) + 1; rsvp_var_t *var = rsvp_var_init(name); if (!var) return NULL; Loading
src/rsvp.h +3 −2 Original line number Diff line number Diff line Loading @@ -110,12 +110,13 @@ extern int rsvp_data_add_var(rsvp_data_t* data, rsvp_var_t* var); extern int rsvp_data_add_vars(rsvp_data_t* data, unsigned int count, ...); /** * @brief Convert rsvp_data_t to a string of raw RSVP data * @brief Convert rsvp_data_t to a string of raw RSVP data. Remember to free the returned string * * @param data Data to convert * @param double_precision Number of decimals for for double values * @return char* String of raw RSVP data */ extern char* rsvp_data_to_string(rsvp_data_t* data); extern char* rsvp_data_to_string(rsvp_data_t* data, int double_precision); /** * @brief Print the RSVP data struct to stdout Loading
tests/CMakeLists.txt +8 −8 Original line number Diff line number Diff line cmake_minimum_required(VERSION 3.20) project(test) project(tests) set(C_TEST c_test) set(CPP_TEST) enable_testing() add_executable(${C_TEST} rsvp_test.cpp) target_link_libraries(${C_TEST} rsvp GTest::gtest_main) add_executable(${PROJECT_NAME} rsvp_test.cpp ../src/rsvp.c) target_link_libraries(${PROJECT_NAME} rsvp GTest::gtest_main) add_executable(${PROJECT_NAME}pp testpp.cpp) target_link_libraries(${PROJECT_NAME}pp rsvppp) add_executable(${CPP_TEST}pp testpp.cpp) target_link_libraries(${CPP_TEST}pp rsvppp) include(GoogleTest) gtest_discover_tests(${PROJECT_NAME}) No newline at end of file gtest_discover_tests(${C_TEST}) No newline at end of file
tests/main.c 0 → 100644 +51 −0 Original line number Diff line number Diff line #include <stdio.h> #include <stdlib.h> int count_char_in_int(int value) { // Take into account the sign int chars = value < 0 ? 1 : 0; int modulo = 0; if (value == 0) return 1; value = abs(value); while (value > 0) { modulo = value % 10; if (modulo == 0) value /= 10; else value = (value - modulo) / 10; chars++; } return chars; } int count_chars_in_double(double value, int precision) { // Start at precision. Plus one to account for the dot int chars = precision + 1; int int_value = (int)value; // Account for negative 0 if (value > -1.0 && value < 0.0) chars += 1; return count_char_in_int(int_value) + chars; } int main() { int val = 11111111; double val1 = -1.87844189641134813; printf("Val: %d, chars: %d\n", val, count_char_in_int(val)); printf("Val: %.5f, chars: %d\n", val1, count_chars_in_double(val1, 5)); return 0; } No newline at end of file