diff --git a/numericx.c b/numericx.c index c3d6b97..695ef4e 100644 --- a/numericx.c +++ b/numericx.c @@ -368,6 +368,152 @@ free_numeral(numeral_ptr* numeral) } } +/** + * @brief Free numericx result + * + * Function frees up the result of numericx_translate(), + * after we are done with it + * + * @param string - char pointer to be free + */ +void +numericx_free(char* string) +{ + free(string); +} + +/** + * @brief Convert numeral_ptr to string + * + * Allocates space for string and converts numeral_ptr* to char* + * + * @param numeral - numeral_ptr to be converted to string + * @param result_with_units_on_the_end - define if result has units on the end + * + * @return char pointer to converted string in case of success + * @return NULL in case of no memory + */ +char* +numeral_to_string(numeral_ptr* numeral, bool result_with_units_on_the_end) +{ + size_t length = 1; + numeral_ptr* numeral_last = numeral; + + while( !(numeral_last->next == NULL) ) + { + ++length; + numeral_last = numeral_last->next; + } + + char* result = malloc((length + 1) * sizeof(char)); + char* tmp = result; + + if( !result_with_units_on_the_end ) + { + for( numeral_ptr* digit = numeral; + !(digit == NULL); digit = digit->next) + { + *tmp = *(digit->symbol); + ++tmp; + } + } + else + { + for( numeral_ptr* digit = numeral_last; + !(digit == NULL); digit = digit->previous) + { + *tmp = *(digit->symbol); + ++tmp; + } + } + + *(tmp) = '\0'; + + return result; +} + +/** + */ +char* +numericx_translate(char* from, bool from_units_on_the_end, bool from_first_number_void, bool from_infinite_base, char* to, bool to_units_on_the_end, bool to_first_number_void, bool to_infinite_base, char* number) +{ + + /* Check if number belongs to it's numerical system */ + if( !is_valid_number(from, number) ) + { + fprintf(stderr, "error: %s: %s.\nValid numerals are: \"%s\"\n", + PROG_NAME, strerror(EDOM), from); + return NULL; + } + + /* _first and _last variables */ + char* from_first = from; + char* from_last = from + (strlen(from) - 1); + + char* to_first = to; + char* to_last = to + (strlen(to) - 1); + + if( from_units_on_the_end ) + { + reverse_string(number); + } + + /* initializing counting and result */ + numeral_ptr* counting = NULL; + numeral_ptr* result = NULL; + + if( from_infinite_base ) + counting = numeral_infinity(from_first, strlen(number)); + else + counting = numeral_infinity(from_first, 1); + + result = numeral_infinity(to_first, 1); + + /* first number void */ + if( !(from_first_number_void && to_first_number_void) ) + { + if( from_first_number_void ) + { + if( strlen(number) == 1 && *number == *from_first ) + { + free_numeral(counting); + free_numeral(result); + fprintf(stderr, "error: %s: unrepresentable void number\n", PROG_NAME); + return NULL; + } + decrement_number_string(number, from_first, from_last, from_first); + } + + if( to_first_number_void ) + increment(result, to_first, to_last, to_first); + } + + /* minor optimization for the cycle below */ + char* to_second = NULL; + + if( to_infinite_base ) + to_second = to_first + 1; + + /* increments until it finishes */ + while( !is_the_same(counting, number) ) + { + if( to_infinite_base ) + increment(result, to_first, to_last, to_second); + else + increment(result, to_first, to_last, to_first); + + increment(counting, from_first, from_last, from_first); + } + + /* result to string (result_string) */ + char* result_string = numeral_to_string(result, to_units_on_the_end); + + /* free memory */ + free_numeral(counting); + free_numeral(result); + + return result_string; +} /* ||MAIN FUNCTION|| */ @@ -386,15 +532,22 @@ main(int argc, char* argv[]) exit(EXIT_FAILURE); } - /* Numeral System variables from MACROS */ + /* Number variables to be converted */ + char* number = argv[1]; + + /* Arguments for translation */ char* from = malloc( (strlen(FROM_NUMERICALS) + 1) * sizeof(char) ); char* to = malloc( (strlen(TO_NUMERICALS) + 1) * sizeof(char) ); strcpy(from, FROM_NUMERICALS); strcpy(to, TO_NUMERICALS); - /* Number variables to be converted */ - char* number = argv[1]; + bool to_units_on_the_end = TO_UNITS_ON_THE_END; + bool from_units_on_the_end = FROM_UNITS_ON_THE_END; + bool to_first_number_void = TO_FIRST_NUMBER_VOID; + bool from_first_number_void = FROM_FIRST_NUMBER_VOID; + bool to_infinite_base = TO_INFINITE_BASE; + bool from_infinite_base = FROM_INFINITE_BASE; /* Check if number belongs to it's numerical system */ if( !is_valid_number(from, number) ) @@ -406,76 +559,28 @@ main(int argc, char* argv[]) exit(EDOM); } - /* _first and _last variables */ - char* from_first = from; - char* from_last = from + (strlen(from) - 1); + /* Translation */ + char* result = numericx_translate( + from, from_units_on_the_end, from_first_number_void, from_infinite_base, + to, to_units_on_the_end, to_first_number_void, to_infinite_base, + number); - char* to_first = to; - char* to_last = to + (strlen(to) - 1); - - if( FROM_UNITS_ON_THE_END ) + /* Test for translation failure */ + if( result == NULL ) { - reverse_string(number); + fprintf(stderr, "error: %s: Invalid translation\n", PROG_NAME); + free(from); + free(to); + return EXIT_FAILURE; } - /* initializing counting and result */ - numeral_ptr* counting = NULL; - numeral_ptr* result = NULL; + /* Print */ + printf("%s\n", result); - if( FROM_INFINITE_BASE ) - counting = numeral_infinity(from_first, strlen(number)); - else - counting = numeral_infinity(from_first, 1); - - result = numeral_infinity(to_first, 1); - - /* first number void */ - if( !(FROM_FIRST_NUMBER_VOID && TO_FIRST_NUMBER_VOID) ) - { - if( FROM_FIRST_NUMBER_VOID ) - { - if( strlen(number) == 1 && *number == *from_first ) - { - free(from); - free(to); - free_numeral(counting); - free_numeral(result); - fprintf(stderr, "error: %s: unrepresentable void number\n", PROG_NAME); - exit(EXIT_FAILURE); - } - decrement_number_string(number, from_first, from_last, from_first); - } - - if( TO_FIRST_NUMBER_VOID ) - increment(result, to_first, to_last, to_first); - } - - /* minor optimization for the cycle below */ - char* to_second = NULL; - - if( TO_INFINITE_BASE ) - to_second = to_first + 1; - - /* increments until it finishes */ - while( !is_the_same(counting, number) ) - { - if( TO_INFINITE_BASE ) - increment(result, to_first, to_last, to_second); - else - increment(result, to_first, to_last, to_first); - - increment(counting, from_first, from_last, from_first); - } - - /* print */ - print_numeral(result); - printf("\n"); - - /* free memory */ + /* Free */ free(from); free(to); - free_numeral(counting); - free_numeral(result); + numericx_free(result); return EXIT_SUCCESS; }