Added files
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | bin | ||||||
							
								
								
									
										35
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | .PHONY: all | ||||||
|  | all: gcd/bin/gcd format_bytes/bin/format_bytes format_time/bin/format_time format_time/bin/format_time_ns | ||||||
|  |  | ||||||
|  | format_time/bin/format_time: | ||||||
|  | 	@cd format_time && exec make -s | ||||||
|  |  | ||||||
|  | format_time/bin/format_time_ns: | ||||||
|  | 	@cd format_time && exec make -s | ||||||
|  |  | ||||||
|  | format_bytes/bin/format_bytes: | ||||||
|  | 	@cd format_bytes && exec make -s | ||||||
|  |  | ||||||
|  | gcd/bin/gcd: | ||||||
|  | 	@cd gcd && exec make -s | ||||||
|  |  | ||||||
|  | .PHONY: install | ||||||
|  | install: gcd/bin/gcd format_bytes/bin/format_bytes format_time/bin/format_time format_time/bin/format_time_ns | ||||||
|  | 	@cp -v compress convertUTF8 extract $^ /usr/bin | ||||||
|  | 	@cd /usr/bin && chmod -v u+x compress convertUTF8 extract gcd format_bytes format_time format_time_ns | ||||||
|  |  | ||||||
|  | .PHONY: uninstall | ||||||
|  | uninstall: | ||||||
|  | 	@cd /usr/bin && rm -v compress convertUTF8 extract gcd format_bytes format_time format_time_ns | ||||||
|  |  | ||||||
|  | .PHONY: clean | ||||||
|  | clean: | ||||||
|  | 	@(cd gcd && exec make -s clean) | ||||||
|  | 	@(cd format_bytes && exec make -s clean) | ||||||
|  | 	@(cd format_time && exec make -s clean) | ||||||
|  |  | ||||||
|  | .PHONY: mrproper | ||||||
|  | mrproper: clean | ||||||
|  | 	@(cd gcd && exec make -s mrproper) | ||||||
|  | 	@(cd format_bytes && exec make -s mrproper) | ||||||
|  | 	@(cd format_time && exec make -s mrproper) | ||||||
							
								
								
									
										39
									
								
								format_bytes/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								format_bytes/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | CXX := g++ | ||||||
|  | CFLAGS := -std=c++11 -m64 -Wall -Werror -Wextra -O3 | ||||||
|  |  | ||||||
|  | .PHONY: all | ||||||
|  | all: bin/format_bytes | ||||||
|  |  | ||||||
|  | bin: | ||||||
|  | 	@mkdir -v bin | ||||||
|  |  | ||||||
|  | bin/format_bytes: src/format_bytes.cpp src/toolbox.cpp | check-cxx-works bin | ||||||
|  | 	@echo Compiling $< | ||||||
|  | 	@${CXX} ${CFLAGS} $^ -o $@ | ||||||
|  |  | ||||||
|  | bin/format_bytes_test: src/format_bytes.cpp src/toolbox.cpp src/unit_test.cpp | check-cxx-works bin | ||||||
|  | 	@echo Compiling $^ | ||||||
|  | 	@${CXX} ${CFLAGS} -DTEST $^ -o $@ | ||||||
|  |  | ||||||
|  | .PHONY: install | ||||||
|  | install: bin/format_bytes | ||||||
|  | 	@cp -v $^ /usr/bin | ||||||
|  |  | ||||||
|  | .PHONY: uninstall | ||||||
|  | uninstall: /usr/bin/format_bytes | ||||||
|  | 	@rm -v $^ | ||||||
|  |  | ||||||
|  | .PHONY: test | ||||||
|  | test: bin/format_bytes_test | ||||||
|  | 	@./$^ | ||||||
|  |  | ||||||
|  | .PHONY: clean | ||||||
|  | clean: | ||||||
|  | 	@rm -rfv bin | ||||||
|  |  | ||||||
|  | .PHONY: mrproper | ||||||
|  | mrproper: clean | ||||||
|  |  | ||||||
|  | .PHONY: check-cxx-works | ||||||
|  | check-cxx-works: | ||||||
|  | 	@${CXX} --version >/dev/null 2>&1 || (echo 'Please install a C++ compiler.' && exit 1) | ||||||
							
								
								
									
										66
									
								
								format_bytes/src/format_bytes.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								format_bytes/src/format_bytes.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | #include <string> | ||||||
|  | #include <array> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "toolbox.hpp" | ||||||
|  |  | ||||||
|  | static constexpr const size_t STRING_BUFFER_SIZE = 64; | ||||||
|  | static constexpr const std::array<const char[3], 7> format_prefix = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given numbers of bytes to a human readable format | ||||||
|  |  * | ||||||
|  |  * @param n Number of bytes | ||||||
|  |  * @return Human readable format of the numbers of bytes | ||||||
|  |  */ | ||||||
|  | std::string format_bytes(uint64_t n) noexcept { | ||||||
|  | 	char s[STRING_BUFFER_SIZE] = { 0 }; | ||||||
|  |  | ||||||
|  | 	if(n == 0){ | ||||||
|  | 		sprintf(s, "0%s", format_prefix[0]); | ||||||
|  | 		return s; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	size_t j = 0; | ||||||
|  | 	for(int8_t i = static_cast<int8_t>(format_prefix.size() - 1) * 10; i >= 0; i -= 10){ | ||||||
|  | 		const uint64_t nsi = n >> i; | ||||||
|  | 		if(nsi > 0){ | ||||||
|  | 			const int8_t idx = i / 10; | ||||||
|  | 			j += ullstr(nsi, j, s); | ||||||
|  | 			for(int k = 0; format_prefix[idx][k] > 0; ++k) | ||||||
|  | 				s[j++] = format_prefix[idx][k]; | ||||||
|  | 			s[j++] = ' '; | ||||||
|  | 			n &= u64(-1) >> (64 - i); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Remove trailing character */ | ||||||
|  | 	s[j - 1] = '\0'; | ||||||
|  |  | ||||||
|  | 	return std::string(s); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifndef TEST | ||||||
|  | int32_t main(const int32_t argc, const char* const* argv) noexcept { | ||||||
|  |  | ||||||
|  | 	uint64_t n = 0; | ||||||
|  | 	if (argc > 2) return fprintf(stderr, "Invalid usage : (%s $NUMBER) or (echo $NUMBER | %s)\n", argv[0], argv[0]); | ||||||
|  | 	else if (argc == 2){ | ||||||
|  | 		if(sstrtoull(argv[1], n) == EXIT_FAILURE) | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} else { | ||||||
|  | 		size_t i = 0; | ||||||
|  | 		char c, BUFFER[STRING_BUFFER_SIZE]; | ||||||
|  | 		for(; i < STRING_BUFFER_SIZE && (c = fgetc(stdin)) != EOF; ++i) | ||||||
|  | 			BUFFER[i] = c; | ||||||
|  | 		if(i == STRING_BUFFER_SIZE){ | ||||||
|  | 			fprintf(stderr, "Error while converting to integer : invalid stdin input (too large)\n"); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 		} | ||||||
|  | 		if(sstrtoull(BUFFER, n) == EXIT_FAILURE) | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printf("%s\n", format_bytes(n).c_str()); | ||||||
|  | 	return EXIT_SUCCESS; | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										11
									
								
								format_bytes/src/format_bytes.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								format_bytes/src/format_bytes.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <string> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given numbers of bytes to a human readable format | ||||||
|  |  * | ||||||
|  |  * @param n Number of bytes | ||||||
|  |  * @return Human readable format of the numbers of bytes | ||||||
|  |  */ | ||||||
|  | std::string format_bytes(uint64_t n) noexcept; | ||||||
							
								
								
									
										85
									
								
								format_bytes/src/toolbox.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								format_bytes/src/toolbox.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | #include <cstdlib> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <cstring> | ||||||
|  | #include <limits.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given string to an unsigned 64 bit integer | ||||||
|  |  * | ||||||
|  |  * @param str Input string to convert | ||||||
|  |  * @param n Integer output | ||||||
|  |  * @return EXIT_SUCCESS if succesful otherwise EXIT_FAILURE | ||||||
|  |  */ | ||||||
|  | int32_t sstrtoull(const char* str, uint64_t& n) noexcept { | ||||||
|  | 	errno = 0; | ||||||
|  | 	char* endptr = nullptr; | ||||||
|  | 	const uint64_t a = strtoull(str, &endptr, 10); | ||||||
|  |  | ||||||
|  | 	switch(errno){ | ||||||
|  | 		case 0: | ||||||
|  | 			n = a; | ||||||
|  | 			return EXIT_SUCCESS; | ||||||
|  | 		case ERANGE: | ||||||
|  | 			fprintf(stderr, "Error while converting to integer : numerical result out of range ("); | ||||||
|  | 			if(a == 0) | ||||||
|  | 				fprintf(stderr, "underflow occurred"); | ||||||
|  | 			else if(a == ULLONG_MAX) | ||||||
|  | 				fprintf(stderr, "overflow occurred"); | ||||||
|  | 			else | ||||||
|  | 				fprintf(stderr, "unspecified"); | ||||||
|  | 			fprintf(stderr, ")\n"); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 		default: | ||||||
|  | 			fprintf(stderr, "Unspecified error occurred while converting to integer: %s\n", strerror(errno)); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Swap two given memory values | ||||||
|  |  * | ||||||
|  |  * @tparam T Type of memory placeholder | ||||||
|  |  * @param a Firat memory pointer | ||||||
|  |  * @param b Second memory pointer | ||||||
|  |  */ | ||||||
|  | template<typename T> | ||||||
|  | inline void swap(T* const a, T* const b) noexcept { | ||||||
|  | 	const T temp = *a; | ||||||
|  | 	*a = *b; | ||||||
|  | 	*b = temp; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number to string | ||||||
|  |  * | ||||||
|  |  * @param num Number to convert | ||||||
|  |  * @param offset of the string location to append | ||||||
|  |  * @param str String to append the number to | ||||||
|  |  * @return number of written bytes | ||||||
|  |  */ | ||||||
|  | size_t ullstr(uint64_t num, const size_t offset, char* const str) noexcept { | ||||||
|  | 	size_t i = 0; | ||||||
|  |  | ||||||
|  | 	for (; num > 0; num /= 10) | ||||||
|  | 		str[offset + i++] = num % 10 + '0'; | ||||||
|  |  | ||||||
|  | 	str[offset + i] = '\0'; | ||||||
|  |  | ||||||
|  | 	for (size_t j = 0; j < i / 2; ++j) | ||||||
|  | 		swap(str + offset + j, str + offset + i - j - 1); | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number to string | ||||||
|  |  * | ||||||
|  |  * @param num Number to convert | ||||||
|  |  * @param str String to append the number to | ||||||
|  |  * @return number of written bytes | ||||||
|  |  */ | ||||||
|  | size_t ullstr(uint64_t num, char* const str) noexcept { | ||||||
|  | 	return ullstr(num, 0, str); | ||||||
|  | } | ||||||
							
								
								
									
										126
									
								
								format_bytes/src/toolbox.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								format_bytes/src/toolbox.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Cast a variable to an unsigned 64 bit integer | ||||||
|  |  * | ||||||
|  |  * @tparam T Type of the variable to cast | ||||||
|  |  * @param vae Variable to cast | ||||||
|  |  * @return Casted variable | ||||||
|  |  */ | ||||||
|  | template<typename T> | ||||||
|  | static constexpr uint64_t u64(const T var) noexcept { | ||||||
|  | 	return static_cast<uint64_t>(var); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given string to an unsigned 64 bit integer | ||||||
|  |  * | ||||||
|  |  * @param str Input string to convert | ||||||
|  |  * @param n Integer output | ||||||
|  |  * @return EXIT_SUCCESS if successful otherwise EXIT_FAILURE | ||||||
|  |  */ | ||||||
|  | int32_t sstrtoull(const char* const str, uint64_t& n) noexcept; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Swap two given memory values | ||||||
|  |  * | ||||||
|  |  * @tparam T Type of memory placeholder | ||||||
|  |  * @param a Firat memory pointer | ||||||
|  |  * @param b Second memory pointer | ||||||
|  |  */ | ||||||
|  | inline void swap(char* const a, char* const b) noexcept; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number to string | ||||||
|  |  * | ||||||
|  |  * @param num Number to convert | ||||||
|  |  * @param offset of the string location to append | ||||||
|  |  * @param str String to append the number to | ||||||
|  |  * @return number of written bytes | ||||||
|  |  */ | ||||||
|  | size_t ullstr(uint64_t num, const size_t offset, char* const str) noexcept; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number to string | ||||||
|  |  * | ||||||
|  |  * @param num Number to convert | ||||||
|  |  * @param str String to append the number to | ||||||
|  |  * @return number of written bytes | ||||||
|  |  */ | ||||||
|  | size_t ullstr(uint64_t num, char* const str) noexcept; | ||||||
|  |  | ||||||
|  | namespace AnsiColor { | ||||||
|  | 	constexpr const char* const Reset = "\e[0m"; | ||||||
|  |  | ||||||
|  | 	// Regular | ||||||
|  | 	constexpr const char* const Black = "\e[0;30m"; | ||||||
|  | 	constexpr const char* const Red = "\e[0;31m"; | ||||||
|  | 	constexpr const char* const Green = "\e[0;32m"; | ||||||
|  | 	constexpr const char* const Yellow = "\e[0;33m"; | ||||||
|  | 	constexpr const char* const Blue = "\e[0;34m"; | ||||||
|  | 	constexpr const char* const Purple = "\e[0;35m"; | ||||||
|  | 	constexpr const char* const Cyan = "\e[0;36m"; | ||||||
|  | 	constexpr const char* const White = "\e[0;37m"; | ||||||
|  |  | ||||||
|  | 	// Bold | ||||||
|  | 	constexpr const char* const BoldBlack = "\e[1;30m"; | ||||||
|  | 	constexpr const char* const BoldRed = "\e[1;31m"; | ||||||
|  | 	constexpr const char* const BoldGreen = "\e[1;32m"; | ||||||
|  | 	constexpr const char* const BoldYellow = "\e[1;33m"; | ||||||
|  | 	constexpr const char* const BoldBlue = "\e[1;34m"; | ||||||
|  | 	constexpr const char* const BoldPurple = "\e[1;35m"; | ||||||
|  | 	constexpr const char* const BoldCyan = "\e[1;36m"; | ||||||
|  | 	constexpr const char* const BoldWhite = "\e[1;37m"; | ||||||
|  |  | ||||||
|  | 	// Underline | ||||||
|  | 	constexpr const char* const UnderBlack = "\e[4;30m"; | ||||||
|  | 	constexpr const char* const UnderRed = "\e[4;31m"; | ||||||
|  | 	constexpr const char* const UnderGreen = "\e[4;32m"; | ||||||
|  | 	constexpr const char* const UnderYellow = "\e[4;33m"; | ||||||
|  | 	constexpr const char* const UnderBlue = "\e[4;34m"; | ||||||
|  | 	constexpr const char* const UnderPurple = "\e[4;35m"; | ||||||
|  | 	constexpr const char* const UnderCyan = "\e[4;36m"; | ||||||
|  | 	constexpr const char* const UnderWhite = "\e[4;37m"; | ||||||
|  |  | ||||||
|  | 	// Background | ||||||
|  | 	constexpr const char* const BgBlack = "\e[40m"; | ||||||
|  | 	constexpr const char* const BgRed = "\e[41m"; | ||||||
|  | 	constexpr const char* const BgGreen = "\e[42m"; | ||||||
|  | 	constexpr const char* const BgYellow = "\e[43m"; | ||||||
|  | 	constexpr const char* const BgBlue = "\e[44m"; | ||||||
|  | 	constexpr const char* const BgPurple = "\e[45m"; | ||||||
|  | 	constexpr const char* const BgCyan = "\e[46m"; | ||||||
|  | 	constexpr const char* const BgWhite = "\e[47m"; | ||||||
|  |  | ||||||
|  | 	// High Intensity | ||||||
|  | 	constexpr const char* const HIBlack = "\e[0;90m"; | ||||||
|  | 	constexpr const char* const HIRed = "\e[0;91m"; | ||||||
|  | 	constexpr const char* const HIGreen = "\e[0;92m"; | ||||||
|  | 	constexpr const char* const HIYellow = "\e[0;93m"; | ||||||
|  | 	constexpr const char* const HIBlue = "\e[0;94m"; | ||||||
|  | 	constexpr const char* const HIPurple = "\e[0;95m"; | ||||||
|  | 	constexpr const char* const HICyan = "\e[0;96m"; | ||||||
|  | 	constexpr const char* const HIWhite = "\e[0;97m"; | ||||||
|  |  | ||||||
|  | 	// Bold High Intensity | ||||||
|  | 	constexpr const char* const BoldHIBlack = "\e[1;90m"; | ||||||
|  | 	constexpr const char* const BoldHIRed = "\e[1;91m"; | ||||||
|  | 	constexpr const char* const BoldHIGreen = "\e[1;92m"; | ||||||
|  | 	constexpr const char* const BoldHIYellow = "\e[1;93m"; | ||||||
|  | 	constexpr const char* const BoldHIBlue = "\e[1;94m"; | ||||||
|  | 	constexpr const char* const BoldHIPurple = "\e[1;95m"; | ||||||
|  | 	constexpr const char* const BoldHICyan = "\e[1;96m"; | ||||||
|  | 	constexpr const char* const BoldHIWhite = "\e[1;97m"; | ||||||
|  |  | ||||||
|  | 	// High Intensity Background | ||||||
|  | 	constexpr const char* const HIBgBlack = "\e[0;100m"; | ||||||
|  | 	constexpr const char* const HIBgRed = "\e[0;101m"; | ||||||
|  | 	constexpr const char* const HIBgGreen = "\e[0;102m"; | ||||||
|  | 	constexpr const char* const HIBgYellow = "\e[0;103m"; | ||||||
|  | 	constexpr const char* const HIBgBlue = "\e[0;104m"; | ||||||
|  | 	constexpr const char* const HIBgPurple = "\e[0;105m"; | ||||||
|  | 	constexpr const char* const HIBgCyan = "\e[0;106m"; | ||||||
|  | 	constexpr const char* const HIBgWhite = "\e[0;107m"; | ||||||
|  | }; | ||||||
							
								
								
									
										46
									
								
								format_bytes/src/unit_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								format_bytes/src/unit_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | #include <iostream> | ||||||
|  | #include "toolbox.hpp" | ||||||
|  | #include "format_bytes.hpp" | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Test if a given result is equal of the expected one and log result | ||||||
|  |  * | ||||||
|  |  * @tparam T type of returning values | ||||||
|  |  * @param name of the unit test | ||||||
|  |  * @param expected result of the function call | ||||||
|  |  * @param result of the function | ||||||
|  |  */ | ||||||
|  | template<typename T> | ||||||
|  | void Assert(const char* const name, const T& expected, const T& result) noexcept { | ||||||
|  | 	if (expected != result) | ||||||
|  | 		std::cerr << AnsiColor::Red << "[ ] - " << name << AnsiColor::Reset << " - Expected '" << expected << "' but got '" << result << "' instead\n"; | ||||||
|  | 	else | ||||||
|  | 		std::cout << AnsiColor::Green << "[✓] - " << name << AnsiColor::Reset << "\n"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Test suite for the format_byte output | ||||||
|  |  */ | ||||||
|  | void format_byte_test(void) noexcept { | ||||||
|  | 	std::cout << AnsiColor::BoldWhite << "\tTesting format_byte_size str suite" << AnsiColor::Reset << "\n"; | ||||||
|  |  | ||||||
|  | 	Assert("format_bytes str null",     std::string("0B"),                                            format_bytes(u64(0))); | ||||||
|  | 	Assert("format_bytes str byte",     std::string("1B"),                                            format_bytes(u64(1))); | ||||||
|  | 	Assert("format_bytes str kilobyte", std::string("1KB"),                                           format_bytes(u64(1) << 10)); | ||||||
|  | 	Assert("format_bytes str megabyte", std::string("1MB"),                                           format_bytes(u64(1) << 20)); | ||||||
|  | 	Assert("format_bytes str gigabyte", std::string("1GB"),                                           format_bytes(u64(1) << 30)); | ||||||
|  | 	Assert("format_bytes str terabyte", std::string("1TB"),                                           format_bytes(u64(1) << 40)); | ||||||
|  | 	Assert("format_bytes str petabyte", std::string("1PB"),                                           format_bytes(u64(1) << 50)); | ||||||
|  | 	Assert("format_bytes str exabyte",  std::string("1EB"),                                           format_bytes(u64(1) << 60)); | ||||||
|  | 	// Unsupported due to number of byte bigger than currently supported by ISO c++ | ||||||
|  | 	// Assert("format_bytes zettabyte", std::string("1ZB"),                                              format_bytes(u64(1)<<70)); | ||||||
|  | 	// Assert("format_bytes yottabyte", std::string("1YB"),                                              format_bytes(u64(1)<<80)); | ||||||
|  | 	// uint64_t_MAX == 2**64 == 18446744073709551615 == -1 | ||||||
|  | 	Assert("format_bytes str max",      std::string("15EB 1023PB 1023TB 1023GB 1023MB 1023KB 1023B"), format_bytes(u64(-1))); | ||||||
|  | 	Assert("format_bytes str max",      std::string("15EB 1023PB 1023TB 1023GB 1023MB 1023KB 1023B"), format_bytes(18446744073709551615ull)); | ||||||
|  | 	Assert("format_bytes str longest",  std::string("10EB 1000PB 1000TB 1000GB 1000MB 1000KB 1000B"), format_bytes(12656215539330294760ull)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int32_t main(void) noexcept { | ||||||
|  | 	format_byte_test(); | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								format_time/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								format_time/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | CXX := g++ | ||||||
|  | CFLAGS := -std=c++11 -m64 -Wall -Werror -Wextra -O3 | ||||||
|  |  | ||||||
|  | .PHONY: all | ||||||
|  | all: bin/format_time bin/format_time_ns | ||||||
|  |  | ||||||
|  | bin: | ||||||
|  | 	@mkdir -v bin | ||||||
|  |  | ||||||
|  | bin/format_time: src/format_time.cpp src/toolbox.cpp | check-cxx-works bin | ||||||
|  | 	@echo Compiling $< | ||||||
|  | 	@${CXX} ${CFLAGS} $^ -o $@ | ||||||
|  |  | ||||||
|  | bin/format_time_ns: src/format_time_ns.cpp src/toolbox.cpp | check-cxx-works bin | ||||||
|  | 	@echo Compiling $^ | ||||||
|  | 	@${CXX} ${CFLAGS} $^ -o $@ | ||||||
|  |  | ||||||
|  | bin/format_time_test: src/format_time.cpp src/format_time_ns.cpp src/toolbox.cpp src/unit_test.cpp | check-cxx-works bin | ||||||
|  | 	@echo Compiling $^ | ||||||
|  | 	@${CXX} ${CFLAGS} -DTEST $^ -o $@ | ||||||
|  |  | ||||||
|  | .PHONY: install | ||||||
|  | install: bin/format_time bin/format_time_ns | ||||||
|  | 	@cp -v $^ /usr/bin | ||||||
|  |  | ||||||
|  | .PHONY: uninstall | ||||||
|  | uninstall: /usr/bin/format_time /usr/bin/format_time_ns | ||||||
|  | 	@rm -v $^ | ||||||
|  |  | ||||||
|  | .PHONY: test | ||||||
|  | test: bin/format_time_test | ||||||
|  | 	@./$^ | ||||||
|  |  | ||||||
|  | .PHONY: clean | ||||||
|  | clean: | ||||||
|  | 	@rm -rfv bin | ||||||
|  |  | ||||||
|  | .PHONY: mrproper | ||||||
|  | mrproper: clean | ||||||
|  |  | ||||||
|  | .PHONY: check-cxx-works | ||||||
|  | check-cxx-works: | ||||||
|  | 	@${CXX} --version >/dev/null 2>&1 || (echo 'Please install a C++ compiler.' && exit 1) | ||||||
							
								
								
									
										67
									
								
								format_time/src/format_time.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								format_time/src/format_time.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | |||||||
|  | #include <string> | ||||||
|  | #include <array> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "toolbox.hpp" | ||||||
|  |  | ||||||
|  | static constexpr const size_t STRING_BUFFER_SIZE = 64; | ||||||
|  | static constexpr const uint8_t N_TIMES = 8; | ||||||
|  | static constexpr const char time_formats[N_TIMES + 1] = "smhjwMyc"; | ||||||
|  | static constexpr const std::array<const uint64_t, N_TIMES> time_numbers = { 1, 60, 3600, 86400, 604800, 2629800, 31557600, u64(315576e4) }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number of seconds to a human readable format | ||||||
|  |  * | ||||||
|  |  * @param time Number of seconds | ||||||
|  |  * @return Human readable formatted string | ||||||
|  |  */ | ||||||
|  | std::string format_time(uint64_t time) noexcept { | ||||||
|  | 	char s[STRING_BUFFER_SIZE] = { 0 }; | ||||||
|  |  | ||||||
|  | 	if(time == 0){ | ||||||
|  | 		sprintf(s, "0%c", time_formats[0]); | ||||||
|  | 		return s; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	uint64_t res; | ||||||
|  | 	size_t j = 0; | ||||||
|  | 	for(int8_t i = static_cast<int8_t>(time_numbers.size() - 1); i >= 0; --i) { | ||||||
|  | 		if(time >= time_numbers[i]){ | ||||||
|  | 			res = time / time_numbers[i]; | ||||||
|  | 			time %= time_numbers[i]; | ||||||
|  | 			j += ullstr(res, j, s); | ||||||
|  | 			s[j++] = time_formats[i]; | ||||||
|  | 			s[j++] = ' '; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Remove trailing character */ | ||||||
|  | 	s[j - 1] = '\0'; | ||||||
|  |  | ||||||
|  | 	return std::string(s); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifndef TEST | ||||||
|  | int32_t main(const int32_t argc, const char* const* argv) noexcept { | ||||||
|  |  | ||||||
|  | 	uint64_t n = 0; | ||||||
|  | 	if (argc > 2) return fprintf(stderr, "Invalid usage : (%s $NUMBER) or (echo $NUMBER | %s)\n", argv[0], argv[0]); | ||||||
|  | 	else if (argc == 2){ | ||||||
|  | 		if(sstrtoull(argv[1], n) == EXIT_FAILURE) | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} else { | ||||||
|  | 		size_t i = 0; | ||||||
|  | 		char c, BUFFER[STRING_BUFFER_SIZE]; | ||||||
|  | 		for(; i < STRING_BUFFER_SIZE && (c = fgetc(stdin)) != EOF; ++i) | ||||||
|  | 			BUFFER[i] = c; | ||||||
|  | 		if(i == STRING_BUFFER_SIZE){ | ||||||
|  | 			fprintf(stderr, "Error while converting to integer : invalid stdin input (too large)\n"); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 		} | ||||||
|  | 		if(sstrtoull(BUFFER, n) == EXIT_FAILURE) | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printf("%s\n", format_time(n).c_str()); | ||||||
|  | 	return EXIT_SUCCESS; | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										19
									
								
								format_time/src/format_time.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								format_time/src/format_time.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <string> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number of seconds to a human readable format | ||||||
|  |  * | ||||||
|  |  * @param time Number of seconds | ||||||
|  |  * @return Human readable formatted string | ||||||
|  |  */ | ||||||
|  | std::string format_time(uint64_t time) noexcept; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number of nanoseconds to a human readable format | ||||||
|  |  * | ||||||
|  |  * @param time Number of nanoseconds | ||||||
|  |  * @return Human readable formatted string | ||||||
|  |  */ | ||||||
|  | std::string format_time_ns(uint64_t time) noexcept; | ||||||
							
								
								
									
										73
									
								
								format_time/src/format_time_ns.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								format_time/src/format_time_ns.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | |||||||
|  | #include <string> | ||||||
|  | #include <array> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "toolbox.hpp" | ||||||
|  |  | ||||||
|  | static constexpr const size_t STR_BUFFER_SIZE = 64; | ||||||
|  | static constexpr const int8_t N_TIMES = 11; | ||||||
|  | static constexpr const std::array<const char* const, N_TIMES> time_formats = { "ns", "us", "ms", "s", "m", "h", "j", "w", "M", "y", "c" }; | ||||||
|  | static constexpr const std::array<const uint64_t, N_TIMES> time_numbers = { 1, 1000, 1000000, u64(1e9), u64(6e10), u64(36e11), u64(864e11), | ||||||
|  | 								u64(6048e11), u64(26298e11), u64(315576e11), u64(315576e13) }; | ||||||
|  |  | ||||||
|  | #define STRING_BUFFER_SIZE 64 | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number of nanoseconds to a human readable format | ||||||
|  |  * | ||||||
|  |  * @param time Number of nanoseconds | ||||||
|  |  * @return Human readable formatted string | ||||||
|  |  */ | ||||||
|  | std::string format_time_ns(uint64_t time) noexcept { | ||||||
|  | 	char s[STRING_BUFFER_SIZE] = {0}; | ||||||
|  | 	size_t j = 0; | ||||||
|  |  | ||||||
|  | 	if (time == 0){ | ||||||
|  | 		sprintf(s, "0%s", time_formats[0]); | ||||||
|  | 		return s; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	uint64_t res; | ||||||
|  | 	for (int8_t i = time_numbers.size() - 1; i >= 0; --i) { | ||||||
|  | 		if (time >= time_numbers[i]) { | ||||||
|  | 			res = time / time_numbers[i]; | ||||||
|  | 			time %= time_numbers[i]; | ||||||
|  | 			j += ullstr(res, j, s); | ||||||
|  | 			for(int k = 0; time_formats[i][k] > 0; ++k) | ||||||
|  | 				s[j++] = time_formats[i][k]; | ||||||
|  | 			s[j++] = ' '; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/* Remove trailing character */ | ||||||
|  | 	s[j - 1] = '\0'; | ||||||
|  |  | ||||||
|  | 	std::string ss(s); | ||||||
|  |  | ||||||
|  | 	return ss; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #ifndef TEST | ||||||
|  | int32_t main(const int32_t argc, const char* const* argv) noexcept { | ||||||
|  |  | ||||||
|  | 	uint64_t n = 0; | ||||||
|  | 	if (argc > 2) return fprintf(stderr, "Invalid usage : (%s $NUMBER) or (echo $NUMBER | %s)\n", argv[0], argv[0]); | ||||||
|  | 	else if (argc == 2){ | ||||||
|  | 		if(sstrtoull(argv[1], n) == EXIT_FAILURE) | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} else { | ||||||
|  | 		size_t i = 0; | ||||||
|  | 		char c, BUFFER[STR_BUFFER_SIZE]; | ||||||
|  | 		for(; i < STR_BUFFER_SIZE && (c = fgetc(stdin)) != EOF; ++i) | ||||||
|  | 			BUFFER[i] = c; | ||||||
|  | 		if(i == STR_BUFFER_SIZE){ | ||||||
|  | 			fprintf(stderr, "Error while converting to integer : invalid stdin input (too large)\n"); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 		} | ||||||
|  | 		if(sstrtoull(BUFFER, n) == EXIT_FAILURE) | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	printf("%s\n", format_time_ns(n).c_str()); | ||||||
|  | 	return EXIT_SUCCESS; | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										85
									
								
								format_time/src/toolbox.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								format_time/src/toolbox.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | #include <cstdlib> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <cstring> | ||||||
|  | #include <limits.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given string to an unsigned 64 bit integer | ||||||
|  |  * | ||||||
|  |  * @param str Input string to convert | ||||||
|  |  * @param n Integer output | ||||||
|  |  * @return EXIT_SUCCESS if successful otherwise EXIT_FAILURE | ||||||
|  |  */ | ||||||
|  | int32_t sstrtoull(const char* str, uint64_t& n) noexcept { | ||||||
|  | 	errno = 0; | ||||||
|  | 	char* endptr = nullptr; | ||||||
|  | 	const uint64_t a = strtoull(str, &endptr, 10); | ||||||
|  |  | ||||||
|  | 	switch(errno){ | ||||||
|  | 		case 0: | ||||||
|  | 			n = a; | ||||||
|  | 			return EXIT_SUCCESS; | ||||||
|  | 		case ERANGE: | ||||||
|  | 			fprintf(stderr, "Error while converting to integer : numerical result out of range ("); | ||||||
|  | 			if(a == 0) | ||||||
|  | 				fprintf(stderr, "underflow occurred"); | ||||||
|  | 			else if(a == ULLONG_MAX) | ||||||
|  | 				fprintf(stderr, "overflow occurred"); | ||||||
|  | 			else | ||||||
|  | 				fprintf(stderr, "unspecified"); | ||||||
|  | 			fprintf(stderr, ")\n"); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 		default: | ||||||
|  | 			fprintf(stderr, "Unspecified error occurred while converting to integer: %s\n", strerror(errno)); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Swap two given memory values | ||||||
|  |  * | ||||||
|  |  * @tparam T Type of memory placeholder | ||||||
|  |  * @param a Firat memory pointer | ||||||
|  |  * @param b Second memory pointer | ||||||
|  |  */ | ||||||
|  | template<typename T> | ||||||
|  | inline void swap(T* const a, T* const b) noexcept { | ||||||
|  | 	const T temp = *a; | ||||||
|  | 	*a = *b; | ||||||
|  | 	*b = temp; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number to string | ||||||
|  |  * | ||||||
|  |  * @param num Number to convert | ||||||
|  |  * @param offset of the string location to append | ||||||
|  |  * @param str String to append the number to | ||||||
|  |  * @return number of written bytes | ||||||
|  |  */ | ||||||
|  | size_t ullstr(uint64_t num, const size_t offset, char* const str) noexcept { | ||||||
|  | 	size_t i = 0; | ||||||
|  |  | ||||||
|  | 	for (; num > 0; num /= 10) | ||||||
|  | 		str[offset + i++] = num % 10 + '0'; | ||||||
|  |  | ||||||
|  | 	str[offset + i] = '\0'; | ||||||
|  |  | ||||||
|  | 	for (size_t j = 0; j < i / 2; ++j) | ||||||
|  | 		swap(str + offset + j, str + offset + i - j - 1); | ||||||
|  | 	return i; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number to string | ||||||
|  |  * | ||||||
|  |  * @param num Number to convert | ||||||
|  |  * @param str String to append the number to | ||||||
|  |  * @return number of written bytes | ||||||
|  |  */ | ||||||
|  | size_t ullstr(uint64_t num, char* const str) noexcept { | ||||||
|  | 	return ullstr(num, 0, str); | ||||||
|  | } | ||||||
							
								
								
									
										126
									
								
								format_time/src/toolbox.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								format_time/src/toolbox.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | #pragma once | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Cast a variable to an unsigned 64 bit integer | ||||||
|  |  * | ||||||
|  |  * @tparam T Type of the variable to cast | ||||||
|  |  * @param vae Variable to cast | ||||||
|  |  * @return Casted variable | ||||||
|  |  */ | ||||||
|  | template<typename T> | ||||||
|  | static constexpr uint64_t u64(const T var) noexcept { | ||||||
|  | 	return static_cast<uint64_t>(var); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given string to an unsigned 64 bit integer | ||||||
|  |  * | ||||||
|  |  * @param str Input string to convert | ||||||
|  |  * @param n Integer output | ||||||
|  |  * @return EXIT_SUCCESS if successful otherwise EXIT_FAILURE | ||||||
|  |  */ | ||||||
|  | int32_t sstrtoull(const char* const str, uint64_t& n) noexcept; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Swap two given memory values | ||||||
|  |  * | ||||||
|  |  * @tparam T Type of memory placeholder | ||||||
|  |  * @param a Firat memory pointer | ||||||
|  |  * @param b Second memory pointer | ||||||
|  |  */ | ||||||
|  | inline void swap(char* const a, char* const b) noexcept; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number to string | ||||||
|  |  * | ||||||
|  |  * @param num Number to convert | ||||||
|  |  * @param offset of the string location to append | ||||||
|  |  * @param str String to append the number to | ||||||
|  |  * @return number of written bytes | ||||||
|  |  */ | ||||||
|  | size_t ullstr(uint64_t num, const size_t offset, char* const str) noexcept; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given number to string | ||||||
|  |  * | ||||||
|  |  * @param num Number to convert | ||||||
|  |  * @param str String to append the number to | ||||||
|  |  * @return number of written bytes | ||||||
|  |  */ | ||||||
|  | size_t ullstr(uint64_t num, char* const str) noexcept; | ||||||
|  |  | ||||||
|  | namespace AnsiColor { | ||||||
|  | 	constexpr const char* const Reset = "\e[0m"; | ||||||
|  |  | ||||||
|  | 	// Regular | ||||||
|  | 	constexpr const char* const Black = "\e[0;30m"; | ||||||
|  | 	constexpr const char* const Red = "\e[0;31m"; | ||||||
|  | 	constexpr const char* const Green = "\e[0;32m"; | ||||||
|  | 	constexpr const char* const Yellow = "\e[0;33m"; | ||||||
|  | 	constexpr const char* const Blue = "\e[0;34m"; | ||||||
|  | 	constexpr const char* const Purple = "\e[0;35m"; | ||||||
|  | 	constexpr const char* const Cyan = "\e[0;36m"; | ||||||
|  | 	constexpr const char* const White = "\e[0;37m"; | ||||||
|  |  | ||||||
|  | 	// Bold | ||||||
|  | 	constexpr const char* const BoldBlack = "\e[1;30m"; | ||||||
|  | 	constexpr const char* const BoldRed = "\e[1;31m"; | ||||||
|  | 	constexpr const char* const BoldGreen = "\e[1;32m"; | ||||||
|  | 	constexpr const char* const BoldYellow = "\e[1;33m"; | ||||||
|  | 	constexpr const char* const BoldBlue = "\e[1;34m"; | ||||||
|  | 	constexpr const char* const BoldPurple = "\e[1;35m"; | ||||||
|  | 	constexpr const char* const BoldCyan = "\e[1;36m"; | ||||||
|  | 	constexpr const char* const BoldWhite = "\e[1;37m"; | ||||||
|  |  | ||||||
|  | 	// Underline | ||||||
|  | 	constexpr const char* const UnderBlack = "\e[4;30m"; | ||||||
|  | 	constexpr const char* const UnderRed = "\e[4;31m"; | ||||||
|  | 	constexpr const char* const UnderGreen = "\e[4;32m"; | ||||||
|  | 	constexpr const char* const UnderYellow = "\e[4;33m"; | ||||||
|  | 	constexpr const char* const UnderBlue = "\e[4;34m"; | ||||||
|  | 	constexpr const char* const UnderPurple = "\e[4;35m"; | ||||||
|  | 	constexpr const char* const UnderCyan = "\e[4;36m"; | ||||||
|  | 	constexpr const char* const UnderWhite = "\e[4;37m"; | ||||||
|  |  | ||||||
|  | 	// Background | ||||||
|  | 	constexpr const char* const BgBlack = "\e[40m"; | ||||||
|  | 	constexpr const char* const BgRed = "\e[41m"; | ||||||
|  | 	constexpr const char* const BgGreen = "\e[42m"; | ||||||
|  | 	constexpr const char* const BgYellow = "\e[43m"; | ||||||
|  | 	constexpr const char* const BgBlue = "\e[44m"; | ||||||
|  | 	constexpr const char* const BgPurple = "\e[45m"; | ||||||
|  | 	constexpr const char* const BgCyan = "\e[46m"; | ||||||
|  | 	constexpr const char* const BgWhite = "\e[47m"; | ||||||
|  |  | ||||||
|  | 	// High Intensity | ||||||
|  | 	constexpr const char* const HIBlack = "\e[0;90m"; | ||||||
|  | 	constexpr const char* const HIRed = "\e[0;91m"; | ||||||
|  | 	constexpr const char* const HIGreen = "\e[0;92m"; | ||||||
|  | 	constexpr const char* const HIYellow = "\e[0;93m"; | ||||||
|  | 	constexpr const char* const HIBlue = "\e[0;94m"; | ||||||
|  | 	constexpr const char* const HIPurple = "\e[0;95m"; | ||||||
|  | 	constexpr const char* const HICyan = "\e[0;96m"; | ||||||
|  | 	constexpr const char* const HIWhite = "\e[0;97m"; | ||||||
|  |  | ||||||
|  | 	// Bold High Intensity | ||||||
|  | 	constexpr const char* const BoldHIBlack = "\e[1;90m"; | ||||||
|  | 	constexpr const char* const BoldHIRed = "\e[1;91m"; | ||||||
|  | 	constexpr const char* const BoldHIGreen = "\e[1;92m"; | ||||||
|  | 	constexpr const char* const BoldHIYellow = "\e[1;93m"; | ||||||
|  | 	constexpr const char* const BoldHIBlue = "\e[1;94m"; | ||||||
|  | 	constexpr const char* const BoldHIPurple = "\e[1;95m"; | ||||||
|  | 	constexpr const char* const BoldHICyan = "\e[1;96m"; | ||||||
|  | 	constexpr const char* const BoldHIWhite = "\e[1;97m"; | ||||||
|  |  | ||||||
|  | 	// High Intensity Background | ||||||
|  | 	constexpr const char* const HIBgBlack = "\e[0;100m"; | ||||||
|  | 	constexpr const char* const HIBgRed = "\e[0;101m"; | ||||||
|  | 	constexpr const char* const HIBgGreen = "\e[0;102m"; | ||||||
|  | 	constexpr const char* const HIBgYellow = "\e[0;103m"; | ||||||
|  | 	constexpr const char* const HIBgBlue = "\e[0;104m"; | ||||||
|  | 	constexpr const char* const HIBgPurple = "\e[0;105m"; | ||||||
|  | 	constexpr const char* const HIBgCyan = "\e[0;106m"; | ||||||
|  | 	constexpr const char* const HIBgWhite = "\e[0;107m"; | ||||||
|  | }; | ||||||
							
								
								
									
										155
									
								
								format_time/src/unit_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								format_time/src/unit_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | |||||||
|  | #include <iostream> | ||||||
|  | #include "toolbox.hpp" | ||||||
|  | #include "format_time.hpp" | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Test if a given result is equal of the expected one and log result | ||||||
|  |  * | ||||||
|  |  * @tparam T type of returning values | ||||||
|  |  * @param name of the unit test | ||||||
|  |  * @param expected result of the function call | ||||||
|  |  * @param result of the function | ||||||
|  |  */ | ||||||
|  | template<typename T> | ||||||
|  | void Assert(const char* const name, const T& expected, const T& result) noexcept { | ||||||
|  | 	if (expected != result) | ||||||
|  | 		std::cerr << AnsiColor::Red << "[ ] - " << name << AnsiColor::Reset << " - Expected '" << expected << "' but got '" << result << "' instead\n"; | ||||||
|  | 	else | ||||||
|  | 		std::cout << AnsiColor::Green << "[✓] - " << name << AnsiColor::Reset << "\n"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Test suite for the format_time output | ||||||
|  |  */ | ||||||
|  | void format_time_test(void) noexcept { | ||||||
|  | 	std::cout << AnsiColor::BoldWhite << "\tTesting format_time str suite" << AnsiColor::Reset << "\n"; | ||||||
|  |  | ||||||
|  | 	// https://en.wikipedia.org/wiki/Unit_of_time | ||||||
|  | 	Assert("format_time str null",                      std::string("0s"),                                    format_time(u64(0))); | ||||||
|  | 	Assert("format_time str second",                    std::string("1s"),                                    format_time(u64(1))); | ||||||
|  | 	Assert("format_time str decasecond",                std::string("10s"),                                   format_time(u64(10))); | ||||||
|  | 	Assert("format_time str minute",                    std::string("1m"),                                    format_time(u64(60))); | ||||||
|  | 	Assert("format_time str milliday",                  std::string("1m 26s"),                                format_time(u64(86))); // missing 0.4s due to precision | ||||||
|  | 	Assert("format_time str hectosecond",               std::string("1m 40s"),                                format_time(u64(100))); | ||||||
|  | 	Assert("format_time str kilosecond",                std::string("16m 40s"),                               format_time(u64(1e3))); | ||||||
|  | 	Assert("format_time str hour",                      std::string("1h"),                                    format_time(u64(3600))); | ||||||
|  | 	Assert("format_time str day",                       std::string("1j"),                                    format_time(u64(86400))); | ||||||
|  | 	Assert("format_time str week/sennight",             std::string("1w"),                                    format_time(u64(604800))); | ||||||
|  | 	Assert("format_time str megasecond",                std::string("1w 4j 13h 46m 40s"),                     format_time(u64(1e6))); | ||||||
|  | 	Assert("format_time str fortnight",                 std::string("2w"),                                    format_time(u64(1209600))); | ||||||
|  | 	Assert("format_time str lunar month (draconitic)",  std::string("3w 6j 5h 5m 35s"),                       format_time(u64(2351135))); // missing 0.8 due to precision | ||||||
|  | 	Assert("format_time str lunar month (tropical)",    std::string("3w 6j 7h 43m 4s"),                       format_time(u64(2360584))); // missing 0.7 due to precision | ||||||
|  | 	Assert("format_time str lunar month (sidereal)",    std::string("3w 6j 7h 43m 11s"),                      format_time(u64(2360591))); // missing 0.6 to precision | ||||||
|  | 	Assert("format_time str lunar month (anomalistic)", std::string("3w 6j 13h 18m 33s"),                     format_time(u64(2380713))); // missing 0.2 due to precision | ||||||
|  | 	Assert("format_time str lunar month (synodic)",     std::string("4w 1j 12h 44m 2s"),                      format_time(u64(2551442))); // missing 0.9 due to precision | ||||||
|  | 	Assert("format_time str month",                     std::string("1M"),                                    format_time(u64(2629800))); | ||||||
|  | 	Assert("format_time str quarantine",                std::string("1M 1w 2j 13h 30m"),                      format_time(u64(3456e3))); | ||||||
|  | 	Assert("format_time str semester",                  std::string("4M 4j 6h"),                              format_time(u64(10886400))); | ||||||
|  | 	Assert("format_time str lunar year",                std::string("11M 2w 5j 13h 22m 48s"),                 format_time(u64(30617568))); | ||||||
|  | 	Assert("format_time str common year",               std::string("11M 4w 2j 4h 30m"),                      format_time(u64(31536e3))); | ||||||
|  | 	Assert("format_time str year",                      std::string("1y"),                                    format_time(u64(31557600))); | ||||||
|  | 	Assert("format_time str tropical year",             std::string("11M 4w 2j 10h 18m 45s"),                 format_time(u64(31556925))); // missing 0.216 due to precision | ||||||
|  | 	Assert("format_time str gregorian year",            std::string("11M 4w 2j 10h 19m 12s"),                 format_time(u64(31556952))); | ||||||
|  | 	Assert("format_time str sidereal year",             std::string("1y 9m 9s"),                              format_time(u64(31558149))); // missing 0.7635456 due to precision | ||||||
|  | 	Assert("format_time str leap year",                 std::string("1y 18h"),                                format_time(u64(31622400))); | ||||||
|  | 	Assert("format_time str olympiad",                  std::string("4y"),                                    format_time(u64(126230400))); | ||||||
|  | 	Assert("format_time str lusturm",                   std::string("5y"),                                    format_time(u64(157788e3))); | ||||||
|  | 	Assert("format_time str decade",                    std::string("10y"),                                   format_time(u64(315576e3))); | ||||||
|  | 	Assert("format_time str indiction",                 std::string("15y"),                                   format_time(u64(473364e3))); | ||||||
|  | 	Assert("format_time str score",                     std::string("20y"),                                   format_time(u64(631152e3))); | ||||||
|  | 	Assert("format_time str gigasecond",                std::string("31y 8M 1w 19h 46m 40s"),                 format_time(u64(1e9))); | ||||||
|  | 	Assert("format_time str jubilee",                   std::string("50y"),                                   format_time(u64(157788e4))); | ||||||
|  | 	Assert("format_time str century",                   std::string("1c"),                                    format_time(u64(315576e4))); | ||||||
|  |  | ||||||
|  | 	Assert("format_time str millennium",                std::string("10c"),                                   format_time(u64(315576e5))); | ||||||
|  | 	Assert("format_time str age",                       std::string("257c 72y"),                              format_time(u64(813302467200))); | ||||||
|  | 	Assert("format_time str terasecond",                std::string("3168c 80y 10M 2w 2j 8h 46m 40s"),        format_time(u64(1e13))); | ||||||
|  | 	Assert("format_time str megaannum",                 std::string("10000c"),                                format_time(u64(315576e8))); | ||||||
|  | 	Assert("format_time str petasecond",                std::string("316880c 87y 9M 3w 2j 9h 16m 40s"),       format_time(u64(1e15))); | ||||||
|  | 	Assert("format_time str galactic year",             std::string("2300000c"),                              format_time(u64(7258248e9))); | ||||||
|  | 	Assert("format_time str kalpa",                     std::string("43200000c"),                             format_time(u64(136328832e9))); | ||||||
|  | 	Assert("format_time str eon",                       std::string("10000000c"),                             format_time(u64(315576e11))); | ||||||
|  | 	Assert("format_time str exasecond",                 std::string("316880878c 14y 1w 3j 13h 46m 40s"),      format_time(u64(1e18))); | ||||||
|  | 	// Cannot use number bigger than currently supported ISO C++ | ||||||
|  | 	//Assert("format_time str zettasecond",               std::string(""),                                      format_time(u64(1e21))); | ||||||
|  | 	//Assert("format_time str yottasecond",               std::string(""),                                      format_time(u64(1e24))); | ||||||
|  | 	//Assert("format_time str ronnasecond",               std::string(""),                                      format_time(u64(1e27))); | ||||||
|  | 	//Assert("format_time str quettasecond",              std::string(""),                                      format_time(u64(1e30))); | ||||||
|  | 	// uint64_t MAX == 2**64 == 18446744073709551615 == -1 | ||||||
|  | 	Assert("format_time str max",                       std::string("5845420460c 90y 7M 2w 1j 17h 30m 15s"),  format_time(u64(-1))); | ||||||
|  | 	Assert("format_time str max",                       std::string("5845420460c 90y 7M 2w 1j 17h 30m 15s"),  format_time(18446744073709551615ull)); | ||||||
|  | 	Assert("format_time str longest",                   std::string("1000000000c 10y 10M 3w 6j 10h 10m 10s"), format_time(3155760000344243410ull)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Test suite for the format_time_ns output | ||||||
|  |  */ | ||||||
|  | void format_time_ns_test(void) noexcept { | ||||||
|  | 	std::cout << AnsiColor::BoldWhite << "\tTesting format_time_ns str suite" << AnsiColor::Reset << "\n"; | ||||||
|  |  | ||||||
|  | 	// https://en.wikipedia.org/wiki/Unit_of_time | ||||||
|  | 	Assert("format_time_ns str null",                      std::string("0ns"),                                            format_time_ns(u64(0))); | ||||||
|  | 	Assert("format_time_ns str nanosecond",                std::string("1ns"),                                            format_time_ns(u64(1))); | ||||||
|  | 	Assert("format_time_ns str shake",                     std::string("10ns"),                                           format_time_ns(u64(10))); | ||||||
|  | 	Assert("format_time_ns str microsecond",               std::string("1us"),                                            format_time_ns(u64(1e3))); | ||||||
|  | 	Assert("format_time_ns str millisecond",               std::string("1ms"),                                            format_time_ns(u64(1e6))); | ||||||
|  | 	Assert("format_time_ns str centisecond",               std::string("10ms"),                                           format_time_ns(u64(1e7))); | ||||||
|  | 	Assert("format_time_ns str decisecond",                std::string("100ms"),                                          format_time_ns(u64(1e8))); | ||||||
|  | 	Assert("format_time_ns str second",                    std::string("1s"),                                             format_time_ns(u64(1e9))); | ||||||
|  | 	Assert("format_time_ns str decasecond",                std::string("10s"),                                            format_time_ns(u64(1e10))); | ||||||
|  | 	Assert("format_time_ns str minute",                    std::string("1m"),                                             format_time_ns(u64(6e10))); | ||||||
|  | 	Assert("format_time_ns str milliday",                  std::string("1m 26s 400ms"),                                   format_time_ns(u64(864e8))); | ||||||
|  | 	Assert("format_time_ns str hectosecond",               std::string("1m 40s"),                                         format_time_ns(u64(1e11))); | ||||||
|  | 	Assert("format_time_ns str kilosecond",                std::string("16m 40s"),                                        format_time_ns(u64(1e12))); | ||||||
|  | 	Assert("format_time_ns str hour",                      std::string("1h"),                                             format_time_ns(u64(36e11))); | ||||||
|  | 	Assert("format_time_ns str day",                       std::string("1j"),                                             format_time_ns(u64(864e11))); | ||||||
|  | 	Assert("format_time_ns str week/sennight",             std::string("1w"),                                             format_time_ns(u64(6048e11))); | ||||||
|  | 	Assert("format_time_ns str megasecond",                std::string("1w 4j 13h 46m 40s"),                              format_time_ns(u64(1e15))); | ||||||
|  | 	Assert("format_time_ns str fortnight",                 std::string("2w"),                                             format_time_ns(u64(12096e11))); | ||||||
|  | 	Assert("format_time_ns str lunar month (draconitic)",  std::string("3w 6j 5h 5m 35s 800ms"),                          format_time_ns(u64(23511358e8))); | ||||||
|  | 	Assert("format_time_ns str lunar month (tropical)",    std::string("3w 6j 7h 43m 4s 700ms"),                          format_time_ns(u64(23605847e8))); | ||||||
|  | 	Assert("format_time_ns str lunar month (sidereal)",    std::string("3w 6j 7h 43m 11s 600ms"),                         format_time_ns(u64(23605916e8))); | ||||||
|  | 	Assert("format_time_ns str lunar month (anomalistic)", std::string("3w 6j 13h 18m 33s 200ms"),                        format_time_ns(u64(23807132e8))); | ||||||
|  | 	Assert("format_time_ns str lunar month (synodic)",     std::string("4w 1j 12h 44m 2s 900ms"),                         format_time_ns(u64(25514429e8))); | ||||||
|  | 	Assert("format_time_ns str month",                     std::string("1M"),                                             format_time_ns(u64(26298e11))); | ||||||
|  | 	Assert("format_time_ns str quarantine",                std::string("1M 1w 2j 13h 30m"),                               format_time_ns(u64(3456e12))); | ||||||
|  | 	Assert("format_time_ns str semester",                  std::string("4M 4j 6h"),                                       format_time_ns(u64(108864e11))); | ||||||
|  | 	Assert("format_time_ns str lunar year",                std::string("11M 2w 5j 13h 22m 48s"),                          format_time_ns(u64(30617568e9))); | ||||||
|  | 	Assert("format_time_ns str common year",               std::string("11M 4w 2j 4h 30m"),                               format_time_ns(u64(31536e12))); | ||||||
|  | 	Assert("format_time_ns str year",                      std::string("1y"),                                             format_time_ns(u64(315576e11))); | ||||||
|  | 	Assert("format_time_ns str tropical year",             std::string("11M 4w 2j 10h 18m 45s"),                          format_time_ns(u64(31556925e9))); | ||||||
|  | 	Assert("format_time_ns str gregorian year",            std::string("11M 4w 2j 10h 19m 12s"),                          format_time_ns(u64(31556952e9))); | ||||||
|  | 	Assert("format_time_ns str sidereal year",             std::string("1y 9m 9s"),                                       format_time_ns(u64(31558149e9))); | ||||||
|  | 	Assert("format_time_ns str leap year",                 std::string("1y 18h"),                                         format_time_ns(u64(316224e11))); | ||||||
|  | 	Assert("format_time_ns str olympiad",                  std::string("4y"),                                             format_time_ns(u64(1262304e11))); | ||||||
|  | 	Assert("format_time_ns str lusturm",                   std::string("5y"),                                             format_time_ns(u64(157788e12))); | ||||||
|  | 	Assert("format_time_ns str decade",                    std::string("10y"),                                            format_time_ns(u64(315576e12))); | ||||||
|  | 	Assert("format_time_ns str indiction",                 std::string("15y"),                                            format_time_ns(u64(473364e12))); | ||||||
|  | 	Assert("format_time_ns str score",                     std::string("20y"),                                            format_time_ns(u64(631152e12))); | ||||||
|  | 	Assert("format_time_ns str gigasecond",                std::string("31y 8M 1w 19h 46m 40s"),                          format_time_ns(u64(1e18))); | ||||||
|  | 	Assert("format_time_ns str jubilee",                   std::string("50y"),                                            format_time_ns(u64(157788e13))); | ||||||
|  | 	Assert("format_time_ns str century",                   std::string("1c"),                                             format_time_ns(u64(315576e13))); | ||||||
|  | 	// Cannot use number bigger than currently supported ISO C++ | ||||||
|  | 	//Assert("format_time_ns str millennium",                std::string("10c"),                                            format_time_ns(u64(315576e14))); | ||||||
|  | 	//Assert("format_time_ns str age",                       std::string("257c 72y"),                                       format_time_ns(u64(8133024672e11))); | ||||||
|  | 	//Assert("format_time_ns str terasecond",                std::string("3168c 80y 10M 2w 2j 8h 46m 40s"),                 format_time_ns(u64(1e22))); | ||||||
|  | 	//Assert("format_time_ns str megaannum",                 std::string("10000c"),                                         format_time_ns(u64(315576e17))); | ||||||
|  | 	//Assert("format_time_ns str petasecond",                std::string("316880c 87y 9M 3w 2j 9h 16m 40s"),                format_time_ns(u64(1e24))); | ||||||
|  | 	//Assert("format_time_ns str galactic year",             std::string("2300000c"),                                       format_time_ns(u64(7258248e18))); | ||||||
|  | 	//Assert("format_time_ns str eon",                       std::string("10000000c"),                                      format_time_ns(u64(136328832e18))); | ||||||
|  | 	//Assert("format_time_ns str kalpa",                     std::string("43200000c"),                                      format_time_ns(u64(315576e20))); | ||||||
|  | 	//Assert("format_time_ns str exasecond",                 std::string("316880878c 14y 1w 3j 13h 46m 40s"),               format_time_ns(u64(1e27))); | ||||||
|  | 	//Assert("format_time_ns str zettasecond",               std::string(""),                                               format_time_ns(u64(1e30))); | ||||||
|  | 	//Assert("format_time_ns str yottasecond",               std::string(""),                                               format_time_ns(u64(1e33))); | ||||||
|  | 	//Assert("format_time_ns str ronnasecond",               std::string(""),                                               format_time_ns(u64(1e36))); | ||||||
|  | 	//Assert("format_time_ns str quettasecond",              std::string(""),                                               format_time_ns(u64(1e39))); | ||||||
|  | 	// uint64_t_MAX == 2**64 == 18446744073709551615 == -1 | ||||||
|  | 	Assert("format_time_ns str max",                       std::string("5c 84y 6M 2w 1j 8h 34m 33s 709ms 551us 615ns"),   format_time_ns(u64(-1))); | ||||||
|  | 	Assert("format_time_ns str max",                       std::string("5c 84y 6M 2w 1j 8h 34m 33s 709ms 551us 615ns"),   format_time_ns(18446744073709551615ull)); | ||||||
|  | 	Assert("format_time_ns str longest",                   std::string("1c 10y 10M 3w 6j 10h 10m 10s 100ms 100us 100ns"), format_time_ns(3500003410100100100ull)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int32_t main(void) noexcept { | ||||||
|  | 	format_time_test(); | ||||||
|  | 	format_time_ns_test(); | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								gcd/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								gcd/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | CXX := g++ | ||||||
|  | CFLAGS := -std=c++11 -m64 -Wall -Werror -Wextra -O3 | ||||||
|  |  | ||||||
|  | .PHONY: all | ||||||
|  | all: bin/gcd | ||||||
|  |  | ||||||
|  | bin: | ||||||
|  | 	@mkdir -v bin | ||||||
|  |  | ||||||
|  | bin/gcd: src/gcd.cpp | check-cxx-works bin | ||||||
|  | 	@echo Compiling $< | ||||||
|  | 	@${CXX} ${CFLAGS} $^ -o $@ | ||||||
|  |  | ||||||
|  | .PHONY: install | ||||||
|  | install: bin/gcd | ||||||
|  | 	@cp -v $^ /usr/bin | ||||||
|  |  | ||||||
|  | .PHONY: uninstall | ||||||
|  | uninstall: /usr/bin/gcd | ||||||
|  | 	@rm -v $^ | ||||||
|  |  | ||||||
|  | .PHONY: clean | ||||||
|  | clean: | ||||||
|  | 	@rm -rfv bin | ||||||
|  |  | ||||||
|  | .PHONY: mrproper | ||||||
|  | mrproper: clean | ||||||
|  |  | ||||||
|  | .PHONY: check-cxx-works | ||||||
|  | check-cxx-works: | ||||||
|  | 	@${CXX} --version >/dev/null 2>&1 || (echo 'Please install a C++ compiler.' && exit 1) | ||||||
							
								
								
									
										63
									
								
								gcd/src/gcd.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								gcd/src/gcd.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | #include <cstdlib> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <cstring> | ||||||
|  | #include <limits.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Calculate the greatest common divisor (GCD) | ||||||
|  |  * | ||||||
|  |  * @param a First integer | ||||||
|  |  * @param b Second integer | ||||||
|  |  * @return greatest common divisor between a and b | ||||||
|  |  */ | ||||||
|  | constexpr int64_t gcd(const int64_t& a, const int64_t& b) noexcept { return a == 0 ? b : gcd(b % a, a); } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @brief Convert a given string to a 64 bit integer | ||||||
|  |  * | ||||||
|  |  * @param str Input string to convert | ||||||
|  |  * @param n Integer output | ||||||
|  |  * @return EXIT_SUCCESS if successful otherwise EXIT_FAILURE | ||||||
|  |  */ | ||||||
|  | int32_t sstrtoll(const char* const str, int64_t& n) noexcept { | ||||||
|  | 	errno = 0; | ||||||
|  | 	char* endptr = nullptr; | ||||||
|  | 	const int64_t a = strtoll(str, &endptr, 10); | ||||||
|  |  | ||||||
|  | 	switch(errno){ | ||||||
|  | 		case 0: | ||||||
|  | 			n = a; | ||||||
|  | 			return EXIT_SUCCESS; | ||||||
|  | 		case ERANGE: | ||||||
|  | 			fprintf(stderr, "Error while converting to integer : numerical result out of range ("); | ||||||
|  | 			if(a == LLONG_MIN) | ||||||
|  | 				fprintf(stderr, "underflow occurred"); | ||||||
|  | 			else if(a == LLONG_MAX) | ||||||
|  | 				fprintf(stderr, "overflow occurred"); | ||||||
|  | 			else | ||||||
|  | 				fprintf(stderr, "unspecified"); | ||||||
|  | 			fprintf(stderr, ")\n"); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 		default: | ||||||
|  | 			fprintf(stderr, "Unspecified error occurred while converting to integer: %s\n", strerror(errno)); | ||||||
|  | 			return EXIT_FAILURE; | ||||||
|  | 	} | ||||||
|  | 	n = a; | ||||||
|  | 	return EXIT_SUCCESS; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int32_t main(const int32_t argc, const char* const* argv) noexcept { | ||||||
|  | 	if (argc != 3){ | ||||||
|  | 		fprintf(stderr, "Syntax : gcd number1 number2\n"); | ||||||
|  | 		return EXIT_FAILURE; | ||||||
|  | 	} | ||||||
|  | 	int64_t a, b; | ||||||
|  | 	if(sstrtoll(argv[1], a) == EXIT_FAILURE) return EXIT_FAILURE; | ||||||
|  | 	if(sstrtoll(argv[2], b) == EXIT_FAILURE) return EXIT_FAILURE; | ||||||
|  |  | ||||||
|  | 	const int64_t hcf = gcd(std::abs(a), std::abs(b)); | ||||||
|  | 	printf("Common factor = %ld\nResult = %ld/%ld\n", hcf, a / hcf, b / hcf); | ||||||
|  | 	return EXIT_SUCCESS; | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user