From 61f03ecce236c51b1104e557ab02d63c59a68fab Mon Sep 17 00:00:00 2001 From: Charles Nicholson Date: Sun, 26 Dec 2021 12:19:28 -0500 Subject: [PATCH] Size golfing (#124) * delete a few cases and pre-initialize precision to 0 * remove a few elses * explicit functions for npf_min and npf_max, let the compiler decide what's smaller * no switch enum warnings on clang linux * min/med/max golfing CI * update the README * update the README * update the README * fix x64 size report flag typo --- .github/workflows/presubmit.yml | 45 ++++++++------ CMakeLists.txt | 3 +- README.md | 82 ++++++++++++------------ nanoprintf.h | 106 +++++++++++++------------------- 4 files changed, 113 insertions(+), 123 deletions(-) diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml index dc906d7..207a050 100644 --- a/.github/workflows/presubmit.yml +++ b/.github/workflows/presubmit.yml @@ -123,44 +123,53 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Cortex-M0 Minimal + - name: Cortex-M0 shell: bash run: | - arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -Os -x c -c -o cm0-min.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' . /work/venv/bin/activate + + echo Minimal: + arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -Os -x c -c -o cm0-min.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' arm-none-eabi-nm --print-size --size-sort cm0-min.o | python tests/size_report.py - - name: Cortex-M0 Everything - shell: bash - run: | + echo Medium: + arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -Os -x c -c -o cm0-med.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' + arm-none-eabi-nm --print-size --size-sort cm0-med.o | python tests/size_report.py + + echo Maximal: arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -Os -x c -c -o cm0-max.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=1 - <<< '#include "nanoprintf.h"' - . /work/venv/bin/activate arm-none-eabi-nm --print-size --size-sort cm0-max.o | python tests/size_report.py - - name: Cortex-M4 Minimal + - name: Cortex-M4 shell: bash run: | - arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Os -x c -c -o cm4-min.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' . /work/venv/bin/activate + + echo Minimal: + arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Os -x c -c -o cm4-min.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' arm-none-eabi-nm --print-size --size-sort cm4-min.o | python tests/size_report.py - - name: Cortex-M4 Everything - shell: bash - run: | + echo Medium: + arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Os -x c -c -o cm4-med.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' + arm-none-eabi-nm --print-size --size-sort cm4-med.o | python tests/size_report.py + + echo Maximal: arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Os -x c -c -o cm4-max.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=1 - <<< '#include "nanoprintf.h"' - . /work/venv/bin/activate arm-none-eabi-nm --print-size --size-sort cm4-max.o | python tests/size_report.py - - name: x64 Minimal + - name: x64 shell: bash run: | - gcc -Os -x c -c -o x64-min.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' . /work/venv/bin/activate + + echo Minimal: + gcc -Os -x c -c -o x64-min.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' nm --print-size --size-sort x64-min.o | python tests/size_report.py - - name: x64 Everything - shell: bash - run: | + echo Medium: + gcc -Os -x c -c -o x64-med.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' + nm --print-size --size-sort x64-med.o | python tests/size_report.py + + echo Maximal: gcc -Os -x c -c -o x64-max.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=1 - <<< '#include "nanoprintf.h"' - . /work/venv/bin/activate nm --print-size --size-sort x64-max.o | python tests/size_report.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 4033e40..3475341 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,14 +35,13 @@ else() -Wconversion -Wsign-conversion -Wswitch-default - -Wswitch-enum -Wno-padded -Wno-covered-switch-default -Wno-unused-function) endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - list(APPEND nanoprintf_common_flags -Weverything -Wno-float-equal) + list(APPEND nanoprintf_common_flags -Weverything -Wno-float-equal -Wno-switch-enum) list(APPEND nanoprintf_cxx_flags -Wno-old-style-cast -Wno-c++98-compat-pedantic diff --git a/README.md b/README.md index eaed9f9..0d254ec 100644 --- a/README.md +++ b/README.md @@ -119,51 +119,51 @@ Despite `nano` in the name, there's no way to do away with double entirely, sinc ## Measurement -Compiling with all optional features disabled yields < 1000 bytes of ARM Cortex-M0 object code: +The CI build is set up to use gcc and nm to measure the compiled size of every pull request. See the [Presubmit Checks](https://github.com/charlesnicholson/nanoprintf/actions/workflows/presubmit.yml) "size reports" job output for recent runs. + +Minimal configuration (all features disabled): ``` -Minimal configuration: -00000016 00000002 T npf_bufputc_nop -00000000 00000016 T npf_bufputc -00000384 00000016 T npf_pprintf -000003cc 00000016 T npf_snprintf -0000039a 00000032 T npf_vsnprintf -000000e8 0000004e T npf_itoa_rev -00000136 00000054 T npf_utoa_rev -00000018 000000d0 T npf_parse_format_spec -0000018a 000001fa T npf_vpprintf -total: 0x3e2 (994 bytes) +arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -Os -x c -c -o cm0-min.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' +arm-none-eabi-nm --print-size --size-sort cm0-min.o | python tests/size_report.py + +00000016 00000002 t npf_bufputc_nop +00000000 00000016 t npf_bufputc +0000036e 00000016 T npf_pprintf +000003b8 00000016 T npf_snprintf +00000384 00000034 T npf_vsnprintf +00000018 00000356 T npf_vpprintf + +Total size: 0x3ce (974 bytes) ``` -Compiling with field width and precision specifiers enabled yields ~1.6KB: +Medium configuration (field width and precision specifiers): ``` -"Small" configuration: (field witdh + precision) -00000016 00000002 T npf_bufputc_nop -00000000 00000016 T npf_bufputc -000005ee 00000016 T npf_pprintf -00000638 00000016 T npf_snprintf -00000604 00000034 T npf_vsnprintf -000001ae 0000004e T npf_itoa_rev -000001fc 00000054 T npf_utoa_rev -00000018 00000196 T npf_parse_format_spec -00000250 0000039e T npf_vpprintf -total: 0x6a8 (1614 bytes) +arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -Os -x c -c -o cm0-med.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=0 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=0 - <<< '#include "nanoprintf.h"' +arm-none-eabi-nm --print-size --size-sort cm0-med.o | python tests/size_report.py + +00000016 00000002 t npf_bufputc_nop +00000000 00000016 t npf_bufputc +0000065e 00000016 T npf_pprintf +000006a8 00000016 T npf_snprintf +00000674 00000034 T npf_vsnprintf +00000018 00000646 T npf_vpprintf + +Total size: 0x6be (1726) bytes ``` -Compiling with all optional features enabled is closer to ~2.5KB: +Maximal configuration (field width, precision, large int, writeback, floating point): ``` -Everything: -00000016 00000002 T npf_bufputc_nop -00000000 00000016 T npf_bufputc -000009ca 00000016 T npf_pprintf -00000a14 00000016 T npf_snprintf -000009e0 00000034 T npf_vsnprintf -00000204 0000005c T npf_itoa_rev -00000260 00000078 T npf_utoa_rev -000002d8 000000e0 T npf_fsplit_abs -000003b8 00000108 T npf_ftoa_rev -00000018 000001ec T npf_parse_format_spec -000004c0 0000050a T npf_vpprintf -total: 0xa2a (2602 bytes) +arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -Os -x c -c -o cm0-max.o -DNANOPRINTF_IMPLEMENTATION -DNANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_LARGE_FORMAT_SPECIFIERS=1 -DNANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS=1 - <<< '#include "nanoprintf.h"' +arm-none-eabi-nm --print-size --size-sort cm0-max.o | python tests/size_report.py + +00000016 00000002 t npf_bufputc_nop +00000000 00000016 t npf_bufputc +00000a2c 00000016 T npf_pprintf +00000a74 00000016 T npf_snprintf +00000a42 00000032 T npf_vsnprintf +00000018 00000a14 T npf_vpprintf + +Total size: 0xa8a (2698) bytes ``` ## Development @@ -181,7 +181,7 @@ nanoprintf uses GitHub Actions for all continuous integration builds. The GitHub The matrix builds [Debug, Release] x [32-bit, 64-bit] x [Mac, Windows, Linux] x [gcc, clang, msvc], minus the 32-bit clang Mac configurations. -I took the very thorough test suite from the [printf](https://github.com/eyalroz/printf/blob/master/test/test_suite.cpp) library and ported it to nanoprintf. It exists as a submodule for licensing purposes- nanoprintf is public domain, and "printf" is MIT, so the modified test suite is optional and excluded by default unless you retrieve it by updating submodules. CI uses it; build with it locally by running `./b --paland`. +One test suite is a fork from the [printf test suite](), which is MIT licensed. It exists as a submodule for licensing purposes- nanoprintf is public domain, so this particular test suite is optional and excluded by default. To build it, retrieve it by updating submodules and add the `--paland` flag to your `./b` invocation. It is not required to use nanoprintf at all. ## Limitations @@ -191,4 +191,6 @@ Currently the only supported float conversions are the decimal forms: `%f` and ` ## Acknowledgments -Float-to-int conversion is done using [Wojciech Muła](mailto:zdjęcia@garnek.pl)'s float -> 64:64 fixed [algorithm](http://0x80.pl/notesen/2015-12-29-float-to-string.html). +I implemented Float-to-int conversion using the ideas from [Wojciech Muła](mailto:zdjęcia@garnek.pl)'s [float -> 64:64 fixed algorithm](http://0x80.pl/notesen/2015-12-29-float-to-string.html). + +I ported the [printf test suite](https://github.com/eyalroz/printf/blob/master/test/test_suite.cpp) to nanoprintf. It was originally from the [mpaland printf project](https://github.com/mpaland/printf) codebase but adopted and improved by [Eyal Rozenberg](https://github.com/eyalroz) and others. (Nanoprintf has many of its own tests, but these are also very thorough and very good!) diff --git a/nanoprintf.h b/nanoprintf.h index 7b72323..b3ef57e 100644 --- a/nanoprintf.h +++ b/nanoprintf.h @@ -231,7 +231,7 @@ typedef struct { typedef uintmax_t npf_uint_t; #endif -NPF_VISIBILITY int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec); +static int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec); typedef struct { char *dst; @@ -239,18 +239,25 @@ typedef struct { size_t cur; } npf_bufputc_ctx_t; -NPF_VISIBILITY void npf_bufputc(int c, void *ctx); -NPF_VISIBILITY void npf_bufputc_nop(int c, void *ctx); -NPF_VISIBILITY int npf_itoa_rev(char *buf, npf_int_t i); -NPF_VISIBILITY int npf_utoa_rev(char *buf, npf_uint_t i, unsigned base, - npf_format_spec_conversion_case_t cc); +static void npf_bufputc(int c, void *ctx); +static void npf_bufputc_nop(int c, void *ctx); +static int npf_itoa_rev(char *buf, npf_int_t i); +static int npf_utoa_rev(char *buf, + npf_uint_t i, + unsigned base, + npf_format_spec_conversion_case_t cc); + #if NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS == 1 -NPF_VISIBILITY int npf_fsplit_abs(float f, uint64_t *out_int_part, - uint64_t *out_frac_part, - int *out_frac_base10_neg_e); -NPF_VISIBILITY int npf_ftoa_rev(char *buf, float f, unsigned base, - npf_format_spec_conversion_case_t cc, - int *out_frac_chars); +static int npf_fsplit_abs(float f, + uint64_t *out_int_part, + uint64_t *out_frac_part, + int *out_frac_base10_neg_e); + +static int npf_ftoa_rev(char *buf, + float f, + unsigned base, + npf_format_spec_conversion_case_t cc, + int *out_frac_chars); #endif #if NANOPRINTF_USE_FLOAT_FORMAT_SPECIFIERS == 1 @@ -266,8 +273,8 @@ NPF_VISIBILITY int npf_ftoa_rev(char *buf, float f, unsigned base, #endif #endif -#define NPF_MIN(x, y) ((x) < (y) ? (x) : (y)) -#define NPF_MAX(x, y) ((x) > (y) ? (x) : (y)) +static int npf_min(int x, int y) { return (x < y) ? x : y; } +static int npf_max(int x, int y) { return (x > y) ? x : y; } int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec) { char const *cur = format; @@ -340,9 +347,7 @@ int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec) { /* ignore negative precision */ out_spec->precision_type = NPF_FMT_SPEC_PRECISION_NONE; ++cur; - while ((*cur >= '0') && (*cur <= '9')) { - ++cur; - } + while ((*cur >= '0') && (*cur <= '9')) { ++cur; } } else { out_spec->precision = 0; out_spec->precision_type = NPF_FMT_SPEC_PRECISION_LITERAL; @@ -463,16 +468,8 @@ int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec) { #if NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS == 1 if ((out_spec->precision_type == NPF_FMT_SPEC_PRECISION_NONE) || (out_spec->precision_type == NPF_FMT_SPEC_PRECISION_STAR)) { + out_spec->precision = 0; switch (out_spec->conv_spec) { - case NPF_FMT_SPEC_CONV_PERCENT: - case NPF_FMT_SPEC_CONV_CHAR: - case NPF_FMT_SPEC_CONV_STRING: - case NPF_FMT_SPEC_CONV_POINTER: -#if NANOPRINTF_USE_WRITEBACK_FORMAT_SPECIFIERS == 1 - case NPF_FMT_SPEC_CONV_WRITEBACK: -#endif - out_spec->precision = 0; - break; case NPF_FMT_SPEC_CONV_SIGNED_INT: case NPF_FMT_SPEC_CONV_OCTAL: case NPF_FMT_SPEC_CONV_HEX_INT: @@ -495,9 +492,7 @@ int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec) { void npf_bufputc(int c, void *ctx) { npf_bufputc_ctx_t *bpc = (npf_bufputc_ctx_t *)ctx; - if (bpc->cur < bpc->len - 1) { - bpc->dst[bpc->cur++] = (char)c; - } + if (bpc->cur < bpc->len - 1) { bpc->dst[bpc->cur++] = (char)c; } } void npf_bufputc_nop(int c, void *ctx) { @@ -507,30 +502,21 @@ void npf_bufputc_nop(int c, void *ctx) { int npf_itoa_rev(char *buf, npf_int_t i) { char *dst = buf; - if (i == 0) { - *dst++ = '0'; - } else { - int const neg = (i < 0) ? -1 : 1; - while (i) { - *dst++ = (char)('0' + (neg * (i % 10))); - i /= 10; - } - } + if (i == 0) { *dst++ = '0'; } + int const neg = (i < 0) ? -1 : 1; + while (i) { *dst++ = (char)('0' + (neg * (i % 10))); i /= 10; } return (int)(dst - buf); } int npf_utoa_rev(char *buf, npf_uint_t i, unsigned base, npf_format_spec_conversion_case_t cc) { char *dst = buf; - if (i == 0) { - *dst++ = '0'; - } else { - unsigned const base_c = (cc == NPF_FMT_SPEC_CONV_CASE_LOWER) ? 'a' : 'A'; - while (i) { - unsigned const d = (unsigned)(i % base); - i /= base; - *dst++ = (d < 10) ? (char)('0' + d) : (char)(base_c + (d - 10)); - } + if (i == 0) { *dst++ = '0'; } + unsigned const base_c = (cc == NPF_FMT_SPEC_CONV_CASE_LOWER) ? 'a' : 'A'; + while (i) { + unsigned const d = (unsigned)(i % base); + *dst++ = (d < 10) ? (char)('0' + d) : (char)(base_c + (d - 10)); + i /= base; } return (int)(dst - buf); } @@ -736,7 +722,7 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list vlist) { fs.precision_type = NPF_FMT_SPEC_PRECISION_LITERAL; fs.precision = precision; } else { // Negative precision is ignored. - fs.precision_type = NPF_FMT_SPEC_PRECISION_NONE; + fs.precision_type = NPF_FMT_SPEC_PRECISION_NONE; } } #endif @@ -756,12 +742,12 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list vlist) { case NPF_FMT_SPEC_CONV_STRING: { // 's' char *s = va_arg(vlist, char *); cbuf = s; - while (*s) ++s; + while (*s) { ++s; } cbuf_len = (int)(s - cbuf); #if NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS == 1 if (fs.precision_type == NPF_FMT_SPEC_PRECISION_LITERAL) { // precision modifier truncates strings - cbuf_len = NPF_MIN(fs.precision, cbuf_len); + cbuf_len = npf_min(fs.precision, cbuf_len); } #endif } break; @@ -839,9 +825,7 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list vlist) { // alt form adds '0' octal, ok to add immediately if (val && fs.alternative_form) { - if (fs.conv_spec == NPF_FMT_SPEC_CONV_OCTAL) { - cbuf[cbuf_len++] = '0'; - } + if (fs.conv_spec == NPF_FMT_SPEC_CONV_OCTAL) { cbuf[cbuf_len++] = '0'; } } // alt form adds '0x' hex but can't write it yet. @@ -931,9 +915,7 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list vlist) { #endif { pad_c = '0'; } } - } else { - pad_c = ' '; - } + } else { pad_c = ' '; } } #endif @@ -943,10 +925,10 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list vlist) { if (!inf_or_nan) { // float precision is after the decimal point int const precision_start = (fs.conv_spec == NPF_FMT_SPEC_CONV_FLOAT_DECIMAL) ? frac_chars : cbuf_len; - prec_pad = NPF_MAX(0, fs.precision - precision_start); + prec_pad = npf_max(0, fs.precision - precision_start); } #elif NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS == 1 - prec_pad = NPF_MAX(0, fs.precision - cbuf_len); + prec_pad = npf_max(0, fs.precision - cbuf_len); #endif } @@ -963,7 +945,7 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list vlist) { #if NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS == 1 field_pad -= prec_pad; #endif // NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS - field_pad = NPF_MAX(0, field_pad); + field_pad = npf_max(0, field_pad); #endif // NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS #if NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS == 1 @@ -1038,18 +1020,16 @@ int npf_vpprintf(npf_putc pc, void *pc_ctx, char const *format, va_list vlist) { int npf_pprintf(npf_putc pc, void *pc_ctx, char const *format, ...) { va_list val; - int rv; va_start(val, format); - rv = npf_vpprintf(pc, pc_ctx, format, val); + int const rv = npf_vpprintf(pc, pc_ctx, format, val); va_end(val); return rv; } int npf_snprintf(char *buffer, size_t bufsz, const char *format, ...) { va_list val; - int rv; va_start(val, format); - rv = npf_vsnprintf(buffer, bufsz, format, val); + int const rv = npf_vsnprintf(buffer, bufsz, format, val); va_end(val); return rv; }