From 675827558fc15fe5544f498b65ccca49688741f0 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Tue, 14 Dec 2021 00:36:36 +0500 Subject: [PATCH] Start working on measurement unit utils --- .gitignore | 1 + Makefile.am | 9 ++++ README.md | 1 + configure.ac | 3 ++ examples/units_human.c | 47 +++++++++++++++++ include/Makefile.am | 3 +- include/kernaux/units.h | 41 +++++++++++++++ src/units.c | 108 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 examples/units_human.c create mode 100644 include/kernaux/units.h create mode 100644 src/units.c diff --git a/.gitignore b/.gitignore index 0406059..d71557f 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ /examples/cmdline /examples/printf /examples/printf_va +/examples/units_human /tests/multiboot2_print1 /tests/multiboot2_print2 /tests/test_cmdline diff --git a/Makefile.am b/Makefile.am index 90129c7..2f7e562 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,6 +60,11 @@ libkernaux_a_SOURCES += src/pfa.c TESTS += tests/test_pfa endif +if ENABLE_UNITS +libkernaux_a_SOURCES += src/units.c +TESTS += examples/units_human +endif + examples_cmdline_SOURCES = \ $(libkernaux_a_SOURCES) \ examples/cmdline.c @@ -72,6 +77,10 @@ examples_printf_va_SOURCES = \ $(libkernaux_a_SOURCES) \ examples/printf_va.c +examples_units_human_SOURCES = \ + $(libkernaux_a_SOURCES) \ + examples/units_human.c + tests_multiboot2_print1_SOURCES = \ $(libkernaux_a_SOURCES) \ tests/multiboot2_print1.c diff --git a/README.md b/README.md index 16ca1ad..d14c96b 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Table of contents API --- +* [Measurement units utils](/include/kernaux/units.h) *(work in progress)* * [Simple command line parser](/include/kernaux/cmdline.h) * [Multiboot 2 (GRUB 2) information parser](/include/kernaux/multiboot2.h) * [Serial console](/include/kernaux/console.h) diff --git a/configure.ac b/configure.ac index fb5bd97..8e21252 100644 --- a/configure.ac +++ b/configure.ac @@ -14,6 +14,7 @@ AC_ARG_ENABLE([cmdline], AS_HELP_STRING([--disable-cmdline], [disable comm AC_ARG_ENABLE([console], AS_HELP_STRING([--disable-console], [disable serial console])) AC_ARG_ENABLE([multiboot2], AS_HELP_STRING([--disable-multiboot2], [disable Multiboot 2 information parser])) AC_ARG_ENABLE([pfa], AS_HELP_STRING([--disable-pfa], [disable Page Frame Allocator])) +AC_ARG_ENABLE([units], AS_HELP_STRING([--disable-units], [disable measurement units utils])) AM_CONDITIONAL([ARCH_I386], [test "$host_cpu" = i386]) AM_CONDITIONAL([ARCH_X86_64], [test "$host_cpu" = x86_64]) @@ -21,6 +22,7 @@ AM_CONDITIONAL([ENABLE_CMDLINE], [test "$enable_cmdline" != no]) AM_CONDITIONAL([ENABLE_CONSOLE], [test "$enable_console" != no]) AM_CONDITIONAL([ENABLE_MULTIBOOT2], [test "$enable_multiboot2" != no]) AM_CONDITIONAL([ENABLE_PFA], [test "$enable_pfa" != no]) +AM_CONDITIONAL([ENABLE_UNITS], [test "$enable_units" != no]) AS_IF([test "$host_cpu" = i386], [AC_DEFINE([ARCH_I386], [1], [architecture is i386])]) AS_IF([test "$host_cpu" = x86_64], [AC_DEFINE([ARCH_X86_64], [1], [architecture is x86_64])]) @@ -28,6 +30,7 @@ AS_IF([test "$enable_cmdline" != no], [AC_DEFINE([ENABLE_CMDLINE], [1], [e AS_IF([test "$enable_console" != no], [AC_DEFINE([ENABLE_CONSOLE], [1], [enabled serial console])]) AS_IF([test "$enable_multiboot2" != no], [AC_DEFINE([ENABLE_MULTIBOOT2], [1], [enabled Multiboot 2 information parser])]) AS_IF([test "$enable_pfa" != no], [AC_DEFINE([ENABLE_PFA], [1], [enabled Page Frame Allocator])]) +AS_IF([test "$enable_units", != no], [AC_DEFINE([ENABLE_UNITS], [1], [enable measurement units utils])]) AM_INIT_AUTOMAKE([1.9 subdir-objects -Wall -Werror]) diff --git a/examples/units_human.c b/examples/units_human.c new file mode 100644 index 0000000..4e6c206 --- /dev/null +++ b/examples/units_human.c @@ -0,0 +1,47 @@ +#include + +#include +#include + +int main() +{ + char buffer[256]; + + kernaux_units_human_raw(123, KERNAUX_UNIT_BIT, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 bit") == 0); + + kernaux_units_human_dec(123, KERNAUX_UNIT_BIT, KERNAUX_UNITPFX_KILO, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 kbit") == 0); + kernaux_units_human_bin(123, KERNAUX_UNIT_BIT, KERNAUX_UNITPFX_KIBI, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 Kibit") == 0); + + kernaux_units_human_dec(123, KERNAUX_UNIT_BIT, KERNAUX_UNITPFX_MEGA, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 Mbit") == 0); + kernaux_units_human_bin(123, KERNAUX_UNIT_BIT, KERNAUX_UNITPFX_MEBI, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 Mibit") == 0); + + kernaux_units_human_dec(123, KERNAUX_UNIT_BIT, KERNAUX_UNITPFX_GIGA, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 Gbit") == 0); + kernaux_units_human_bin(123, KERNAUX_UNIT_BIT, KERNAUX_UNITPFX_GIBI, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 Gibit") == 0); + + kernaux_units_human_raw(123, KERNAUX_UNIT_BYTE, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 Byte") == 0); + + kernaux_units_human_dec(123, KERNAUX_UNIT_BYTE, KERNAUX_UNITPFX_KILO, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 kB") == 0); + kernaux_units_human_bin(123, KERNAUX_UNIT_BYTE, KERNAUX_UNITPFX_KIBI, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 KiB") == 0); + + kernaux_units_human_dec(123, KERNAUX_UNIT_BYTE, KERNAUX_UNITPFX_MEGA, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 MB") == 0); + kernaux_units_human_bin(123, KERNAUX_UNIT_BYTE, KERNAUX_UNITPFX_MEBI, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 MiB") == 0); + + kernaux_units_human_dec(123, KERNAUX_UNIT_BYTE, KERNAUX_UNITPFX_GIGA, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 GB") == 0); + kernaux_units_human_bin(123, KERNAUX_UNIT_BYTE, KERNAUX_UNITPFX_GIBI, buffer, sizeof(buffer)); + assert(strcmp(buffer, "123 GiB") == 0); + + return 0; +} diff --git a/include/Makefile.am b/include/Makefile.am index 603326e..15380ea 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -6,4 +6,5 @@ nobase_include_HEADERS = \ kernaux/multiboot2.h \ kernaux/pfa.h \ kernaux/printf.h \ - kernaux/stdlib.h + kernaux/stdlib.h \ + kernaux/units.h diff --git a/include/kernaux/units.h b/include/kernaux/units.h new file mode 100644 index 0000000..c1f8017 --- /dev/null +++ b/include/kernaux/units.h @@ -0,0 +1,41 @@ +#ifndef KERNAUX_INCLUDED_UNITS +#define KERNAUX_INCLUDED_UNITS + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum KernAux_Unit { + KERNAUX_UNIT_BIT, + KERNAUX_UNIT_BYTE, +}; + +enum KernAux_UnitPrefixDec { + KERNAUX_UNITPFX_KILO, + KERNAUX_UNITPFX_MEGA, + KERNAUX_UNITPFX_GIGA, +}; + +enum KernAux_UnitPrefixBin { + KERNAUX_UNITPFX_KIBI, + KERNAUX_UNITPFX_MEBI, + KERNAUX_UNITPFX_GIBI, +}; + +bool kernaux_units_human_raw(size_t value, enum KernAux_Unit unit, + char *buffer, size_t buffer_size); +bool kernaux_units_human_dec(size_t value, enum KernAux_Unit unit, + enum KernAux_UnitPrefixDec prefix, + char *buffer, size_t buffer_size); +bool kernaux_units_human_bin(size_t value, enum KernAux_Unit unit, + enum KernAux_UnitPrefixBin prefix, + char *buffer, size_t buffer_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/units.c b/src/units.c new file mode 100644 index 0000000..afb0dc4 --- /dev/null +++ b/src/units.c @@ -0,0 +1,108 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +bool kernaux_units_human_raw( + const size_t value, + const enum KernAux_Unit unit, + char *buffer, + const size_t buffer_size +) { + kernaux_itoa(value, buffer, 10); + while (*buffer != '\0') ++buffer; + *(buffer++) = ' '; + + switch (unit) { + case KERNAUX_UNIT_BIT: + *(buffer++) = 'b'; + *(buffer++) = 'i'; + *(buffer++) = 't'; + break; + case KERNAUX_UNIT_BYTE: + *(buffer++) = 'B'; + *(buffer++) = 'y'; + *(buffer++) = 't'; + *(buffer++) = 'e'; + break; + } + *(buffer++) = '\0'; +} + +bool kernaux_units_human_dec( + const size_t value, + const enum KernAux_Unit unit, + const enum KernAux_UnitPrefixDec prefix, + char *buffer, + const size_t buffer_size +) { + kernaux_itoa(value, buffer, 10); + while (*buffer != '\0') ++buffer; + *(buffer++) = ' '; + + switch (prefix) { + case KERNAUX_UNITPFX_KILO: + *(buffer++) = 'k'; + break; + case KERNAUX_UNITPFX_MEGA: + *(buffer++) = 'M'; + break; + case KERNAUX_UNITPFX_GIGA: + *(buffer++) = 'G'; + break; + } + + switch (unit) { + case KERNAUX_UNIT_BIT: + *(buffer++) = 'b'; + *(buffer++) = 'i'; + *(buffer++) = 't'; + break; + case KERNAUX_UNIT_BYTE: + *(buffer++) = 'B'; + break; + } + *(buffer++) = '\0'; +} + +bool kernaux_units_human_bin( + const size_t value, + const enum KernAux_Unit unit, + const enum KernAux_UnitPrefixBin prefix, + char *buffer, + const size_t buffer_size +) { + kernaux_itoa(value, buffer, 10); + while (*buffer != '\0') ++buffer; + *(buffer++) = ' '; + + switch (prefix) { + case KERNAUX_UNITPFX_KIBI: + *(buffer++) = 'K'; + *(buffer++) = 'i'; + break; + case KERNAUX_UNITPFX_MEBI: + *(buffer++) = 'M'; + *(buffer++) = 'i'; + break; + case KERNAUX_UNITPFX_GIBI: + *(buffer++) = 'G'; + *(buffer++) = 'i'; + break; + } + + switch (unit) { + case KERNAUX_UNIT_BIT: + *(buffer++) = 'b'; + *(buffer++) = 'i'; + *(buffer++) = 't'; + break; + case KERNAUX_UNIT_BYTE: + *(buffer++) = 'B'; + break; + } + *(buffer++) = '\0'; +}