pika_vsnprintf.c 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  1. /*
  2. * Copyright (c) 2021, Meco Jianting Man <jiantingman@foxmail.com>
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-11-27 Meco Man porting for rt_vsnprintf as the fully functional
  9. * version
  10. */
  11. /**
  12. * @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
  13. * 2021, Haifa, Palestine/Israel
  14. * @author (c) Marco Paland (info@paland.com)
  15. * 2014-2019, PALANDesign Hannover, Germany
  16. *
  17. * @note Others have made smaller contributions to this file: see the
  18. * contributors page at https://github.com/eyalroz/printf/graphs/contributors
  19. * or ask one of the authors.
  20. *
  21. * @brief Small stand-alone implementation of the printf family of functions
  22. * (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems
  23. * with a very limited resources.
  24. *
  25. * @note the implementations are thread-safe; re-entrant; use no functions from
  26. * the standard library; and do not dynamically allocate any memory.
  27. *
  28. * @license The MIT License (MIT)
  29. *
  30. * Permission is hereby granted, free of charge, to any person obtaining a copy
  31. * of this software and associated documentation files (the "Software"), to deal
  32. * in the Software without restriction, including without limitation the rights
  33. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  34. * copies of the Software, and to permit persons to whom the Software is
  35. * furnished to do so, subject to the following conditions:
  36. *
  37. * The above copyright notice and this permission notice shall be included in
  38. * all copies or substantial portions of the Software.
  39. *
  40. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  41. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  42. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  43. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  44. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  45. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  46. * THE SOFTWARE.
  47. */
  48. #include <stdarg.h>
  49. #include <stdbool.h>
  50. #include <stddef.h>
  51. #include <stdint.h>
  52. #include "PikaObj.h"
  53. #include "pika_adapter_rtt.h"
  54. #if !PIKASCRIPT_VERSION_REQUIRE_MINIMUN(1, 12, 0)
  55. #error "pika_vsnprintf.c requires at least PikaScript 1.12.0"
  56. #endif
  57. // 'ntoa' conversion buffer size, this must be big enough to hold one converted
  58. // numeric number including padded zeros (dynamically created on stack)
  59. #ifndef PRINTF_INTEGER_BUFFER_SIZE
  60. #define PRINTF_INTEGER_BUFFER_SIZE 32
  61. #endif
  62. // 'ftoa' conversion buffer size, this must be big enough to hold one converted
  63. // float number including padded zeros (dynamically created on stack)
  64. #ifndef PRINTF_FTOA_BUFFER_SIZE
  65. #define PRINTF_FTOA_BUFFER_SIZE 32
  66. #endif
  67. // Support for the decimal notation floating point conversion specifiers (%f,
  68. // %F)
  69. #ifndef PRINTF_SUPPORT_DECIMAL_SPECIFIERS
  70. #define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 1
  71. #endif
  72. // Support for the exponential notatin floating point conversion specifiers (%e,
  73. // %g, %E, %G)
  74. #ifndef PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
  75. #define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 1
  76. #endif
  77. // Default precision for the floating point conversion specifiers (the C
  78. // standard sets this at 6)
  79. #ifndef PRINTF_DEFAULT_FLOAT_PRECISION
  80. #define PRINTF_DEFAULT_FLOAT_PRECISION 6
  81. #endif
  82. // According to the C languages standard, printf() and related functions must be
  83. // able to print any integral number in floating-point notation, regardless of
  84. // length, when using the %f specifier - possibly hundreds of characters,
  85. // potentially overflowing your buffers. In this implementation, all values
  86. // beyond this threshold are switched to exponential notation.
  87. #ifndef PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL
  88. #define PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL 9
  89. #endif
  90. // Support for the long long integral types (with the ll, z and t length
  91. // modifiers for specifiers %d,%i,%o,%x,%X,%u, and with the %p specifier). Note:
  92. // 'L' (long double) is not supported.
  93. #ifndef PRINTF_SUPPORT_LONG_LONG
  94. #define PRINTF_SUPPORT_LONG_LONG 1
  95. #endif
  96. #if PRINTF_SUPPORT_LONG_LONG
  97. typedef unsigned long long printf_unsigned_value_t;
  98. typedef long long printf_signed_value_t;
  99. #else
  100. typedef unsigned long printf_unsigned_value_t;
  101. typedef long printf_signed_value_t;
  102. #endif
  103. #define PRINTF_PREFER_DECIMAL false
  104. #define PRINTF_PREFER_EXPONENTIAL true
  105. ///////////////////////////////////////////////////////////////////////////////
  106. // The following will convert the number-of-digits into an exponential-notation
  107. // literal
  108. #define PRINTF_CONCATENATE(s1, s2) s1##s2
  109. #define PRINTF_EXPAND_THEN_CONCATENATE(s1, s2) PRINTF_CONCATENATE(s1, s2)
  110. #define PRINTF_FLOAT_NOTATION_THRESHOLD \
  111. PRINTF_EXPAND_THEN_CONCATENATE(1e, PRINTF_MAX_INTEGRAL_DIGITS_FOR_DECIMAL)
  112. // internal flag definitions
  113. #define FLAGS_ZEROPAD (1U << 0U)
  114. #define FLAGS_LEFT (1U << 1U)
  115. #define FLAGS_PLUS (1U << 2U)
  116. #define FLAGS_SPACE (1U << 3U)
  117. #define FLAGS_HASH (1U << 4U)
  118. #define FLAGS_UPPERCASE (1U << 5U)
  119. #define FLAGS_CHAR (1U << 6U)
  120. #define FLAGS_SHORT (1U << 7U)
  121. #define FLAGS_LONG (1U << 8U)
  122. #define FLAGS_LONG_LONG (1U << 9U)
  123. #define FLAGS_PRECISION (1U << 10U)
  124. #define FLAGS_ADAPT_EXP (1U << 11U)
  125. #define FLAGS_POINTER (1U << 12U)
  126. // Note: Similar, but not identical, effect as FLAGS_HASH
  127. #define BASE_BINARY 2
  128. #define BASE_OCTAL 8
  129. #define BASE_DECIMAL 10
  130. #define BASE_HEX 16
  131. typedef uint8_t numeric_base_t;
  132. #if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
  133. #include <float.h>
  134. #if FLT_RADIX != 2
  135. #error "Non-binary-radix floating-point types are unsupported."
  136. #endif
  137. #if DBL_MANT_DIG == 24
  138. #define DOUBLE_SIZE_IN_BITS 32
  139. typedef uint32_t double_uint_t;
  140. #define DOUBLE_EXPONENT_MASK 0xFFU
  141. #define DOUBLE_BASE_EXPONENT 127
  142. #elif DBL_MANT_DIG == 53
  143. #define DOUBLE_SIZE_IN_BITS 64
  144. typedef uint64_t double_uint_t;
  145. #define DOUBLE_EXPONENT_MASK 0x7FFU
  146. #define DOUBLE_BASE_EXPONENT 1023
  147. #else
  148. #error "Unsupported double type configuration"
  149. #endif
  150. #define DOUBLE_STORED_MANTISSA_BITS (DBL_MANT_DIG - 1)
  151. typedef union {
  152. double_uint_t U;
  153. double F;
  154. } double_with_bit_access;
  155. // This is unnecessary in C99, since compound initializers can be used,
  156. // but: 1. Some compilers are finicky about this; 2. Some people may want to
  157. // convert this to C89;
  158. // 3. If you try to use it as C++, only C++20 supports compound literals
  159. static inline double_with_bit_access get_bit_access(double x) {
  160. double_with_bit_access dwba;
  161. dwba.F = x;
  162. return dwba;
  163. }
  164. static inline int get_sign(double x) {
  165. // The sign is stored in the highest bit
  166. return get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1);
  167. }
  168. static inline int get_exp2(double_with_bit_access x) {
  169. // The exponent in an IEEE-754 floating-point number occupies a contiguous
  170. // sequence of bits (e.g. 52..62 for 64-bit doubles), but with a non-trivial
  171. // representation: An unsigned offset from some negative value (with the
  172. // extremal offset values reserved for special use).
  173. return (int)((x.U >> DOUBLE_STORED_MANTISSA_BITS) & DOUBLE_EXPONENT_MASK) -
  174. DOUBLE_BASE_EXPONENT;
  175. }
  176. #define PRINTF_ABS(_x) ((_x) > 0 ? (_x) : -(_x))
  177. #endif // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS ||
  178. // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
  179. // Note in particular the behavior here on LONG_MIN or LLONG_MIN; it is valid
  180. // and well-defined, but if you're not careful you can easily trigger undefined
  181. // behavior with -LONG_MIN or -LLONG_MIN
  182. #define ABS_FOR_PRINTING(_x) \
  183. ((printf_unsigned_value_t)((_x) > 0 ? (_x) : -((printf_signed_value_t)_x)))
  184. // output function type
  185. typedef void (*out_fct_type)(char character,
  186. void* buffer,
  187. size_t idx,
  188. size_t maxlen);
  189. // wrapper (used as buffer) for output function type
  190. typedef struct {
  191. void (*fct)(char character, void* arg);
  192. void* arg;
  193. } out_function_wrapper_type;
  194. // internal buffer output
  195. static inline void out_buffer(char character,
  196. void* buffer,
  197. size_t idx,
  198. size_t maxlen) {
  199. if (idx < maxlen) {
  200. ((char*)buffer)[idx] = character;
  201. }
  202. }
  203. // internal null output
  204. static inline void out_discard(char character,
  205. void* buffer,
  206. size_t idx,
  207. size_t maxlen) {
  208. (void)character;
  209. (void)buffer;
  210. (void)idx;
  211. (void)maxlen;
  212. }
  213. // internal secure strlen
  214. // @return The length of the string (excluding the terminating 0) limited by
  215. // 'maxsize'
  216. static inline unsigned int strnlen_s_(const char* str, size_t maxsize) {
  217. const char* s;
  218. for (s = str; *s && maxsize--; ++s)
  219. ;
  220. return (unsigned int)(s - str);
  221. }
  222. // internal test if char is a digit (0-9)
  223. // @return true if char is a digit
  224. static inline bool is_digit_(char ch) {
  225. return (ch >= '0') && (ch <= '9');
  226. }
  227. // internal ASCII string to unsigned int conversion
  228. static unsigned int atoi_(const char** str) {
  229. unsigned int i = 0U;
  230. while (is_digit_(**str)) {
  231. i = i * 10U + (unsigned int)(*((*str)++) - '0');
  232. }
  233. return i;
  234. }
  235. // output the specified string in reverse, taking care of any zero-padding
  236. static size_t out_rev_(out_fct_type out,
  237. char* buffer,
  238. size_t idx,
  239. size_t maxlen,
  240. const char* buf,
  241. size_t len,
  242. unsigned int width,
  243. unsigned int flags) {
  244. const size_t start_idx = idx;
  245. // pad spaces up to given width
  246. if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
  247. for (size_t i = len; i < width; i++) {
  248. out(' ', buffer, idx++, maxlen);
  249. }
  250. }
  251. // reverse string
  252. while (len) {
  253. out(buf[--len], buffer, idx++, maxlen);
  254. }
  255. // append pad spaces up to given width
  256. if (flags & FLAGS_LEFT) {
  257. while (idx - start_idx < width) {
  258. out(' ', buffer, idx++, maxlen);
  259. }
  260. }
  261. return idx;
  262. }
  263. // Invoked by print_integer after the actual number has been printed, performing
  264. // necessary work on the number's prefix (as the number is initially printed in
  265. // reverse order)
  266. static size_t print_integer_finalization(out_fct_type out,
  267. char* buffer,
  268. size_t idx,
  269. size_t maxlen,
  270. char* buf,
  271. size_t len,
  272. bool negative,
  273. numeric_base_t base,
  274. unsigned int precision,
  275. unsigned int width,
  276. unsigned int flags) {
  277. size_t unpadded_len = len;
  278. // pad with leading zeros
  279. {
  280. if (!(flags & FLAGS_LEFT)) {
  281. if (width && (flags & FLAGS_ZEROPAD) &&
  282. (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
  283. width--;
  284. }
  285. while ((flags & FLAGS_ZEROPAD) && (len < width) &&
  286. (len < PRINTF_INTEGER_BUFFER_SIZE)) {
  287. buf[len++] = '0';
  288. }
  289. }
  290. while ((len < precision) && (len < PRINTF_INTEGER_BUFFER_SIZE)) {
  291. buf[len++] = '0';
  292. }
  293. if (base == BASE_OCTAL && (len > unpadded_len)) {
  294. // Since we've written some zeros, we've satisfied the alternative
  295. // format leading space requirement
  296. flags &= ~FLAGS_HASH;
  297. }
  298. }
  299. // handle hash
  300. if (flags & (FLAGS_HASH | FLAGS_POINTER)) {
  301. if (!(flags & FLAGS_PRECISION) && len &&
  302. ((len == precision) || (len == width))) {
  303. // Let's take back some padding digits to fit in what will
  304. // eventually be the format-specific prefix
  305. if (unpadded_len < len) {
  306. len--;
  307. }
  308. if (len && (base == BASE_HEX)) {
  309. if (unpadded_len < len) {
  310. len--;
  311. }
  312. }
  313. }
  314. if ((base == BASE_HEX) && !(flags & FLAGS_UPPERCASE) &&
  315. (len < PRINTF_INTEGER_BUFFER_SIZE)) {
  316. buf[len++] = 'x';
  317. } else if ((base == BASE_HEX) && (flags & FLAGS_UPPERCASE) &&
  318. (len < PRINTF_INTEGER_BUFFER_SIZE)) {
  319. buf[len++] = 'X';
  320. } else if ((base == BASE_BINARY) &&
  321. (len < PRINTF_INTEGER_BUFFER_SIZE)) {
  322. buf[len++] = 'b';
  323. }
  324. if (len < PRINTF_INTEGER_BUFFER_SIZE) {
  325. buf[len++] = '0';
  326. }
  327. }
  328. if (len < PRINTF_INTEGER_BUFFER_SIZE) {
  329. if (negative) {
  330. buf[len++] = '-';
  331. } else if (flags & FLAGS_PLUS) {
  332. buf[len++] = '+'; // ignore the space if the '+' exists
  333. } else if (flags & FLAGS_SPACE) {
  334. buf[len++] = ' ';
  335. }
  336. }
  337. return out_rev_(out, buffer, idx, maxlen, buf, len, width, flags);
  338. }
  339. // An internal itoa-like function
  340. static size_t print_integer(out_fct_type out,
  341. char* buffer,
  342. size_t idx,
  343. size_t maxlen,
  344. printf_unsigned_value_t value,
  345. bool negative,
  346. numeric_base_t base,
  347. unsigned int precision,
  348. unsigned int width,
  349. unsigned int flags) {
  350. char buf[PRINTF_INTEGER_BUFFER_SIZE];
  351. size_t len = 0U;
  352. if (!value) {
  353. if (!(flags & FLAGS_PRECISION)) {
  354. buf[len++] = '0';
  355. flags &= ~FLAGS_HASH;
  356. // We drop this flag this since either the alternative and regular
  357. // modes of the specifier don't differ on 0 values, or (in the case
  358. // of octal) we've already provided the special handling for this
  359. // mode.
  360. } else if (base == BASE_HEX) {
  361. flags &= ~FLAGS_HASH;
  362. // We drop this flag this since either the alternative and regular
  363. // modes of the specifier don't differ on 0 values
  364. }
  365. } else {
  366. do {
  367. const char digit = (char)(value % base);
  368. buf[len++] =
  369. (char)(digit < 10 ? '0' + digit
  370. : (flags & FLAGS_UPPERCASE ? 'A' : 'a') +
  371. digit - 10);
  372. value /= base;
  373. } while (value && (len < PRINTF_INTEGER_BUFFER_SIZE));
  374. }
  375. return print_integer_finalization(out, buffer, idx, maxlen, buf, len,
  376. negative, base, precision, width, flags);
  377. }
  378. #if (PRINTF_SUPPORT_DECIMAL_SPECIFIERS || PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
  379. struct double_components {
  380. int_fast64_t integral;
  381. int_fast64_t fractional;
  382. bool is_negative;
  383. };
  384. #define NUM_DECIMAL_DIGITS_IN_INT64_T 18
  385. #define PRINTF_MAX_PRECOMPUTED_POWER_OF_10 NUM_DECIMAL_DIGITS_IN_INT64_T
  386. static const double powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = {
  387. 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08,
  388. 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17};
  389. #define PRINTF_MAX_SUPPORTED_PRECISION NUM_DECIMAL_DIGITS_IN_INT64_T - 1
  390. // Break up a double number - which is known to be a finite non-negative number
  391. // - into its base-10 parts: integral - before the decimal point, and fractional
  392. // - after it. Taken the precision into account, but does not change it even
  393. // internally.
  394. static struct double_components get_components(double number,
  395. unsigned int precision) {
  396. struct double_components number_;
  397. number_.is_negative = get_sign(number);
  398. double abs_number = (number_.is_negative) ? -number : number;
  399. number_.integral = (int_fast64_t)abs_number;
  400. double remainder =
  401. (abs_number - number_.integral) * powers_of_10[precision];
  402. number_.fractional = (int_fast64_t)remainder;
  403. remainder -= (double)number_.fractional;
  404. if (remainder > 0.5) {
  405. ++number_.fractional;
  406. // handle rollover, e.g. case 0.99 with precision 1 is 1.0
  407. if ((double)number_.fractional >= powers_of_10[precision]) {
  408. number_.fractional = 0;
  409. ++number_.integral;
  410. }
  411. } else if (remainder == 0.5) {
  412. if ((number_.fractional == 0U) || (number_.fractional & 1U)) {
  413. // if halfway, round up if odd OR if last digit is 0
  414. ++number_.fractional;
  415. }
  416. }
  417. if (precision == 0U) {
  418. remainder = abs_number - (double)number_.integral;
  419. if ((!(remainder < 0.5) || (remainder > 0.5)) &&
  420. (number_.integral & 1)) {
  421. // exactly 0.5 and ODD, then round up
  422. // 1.5 -> 2, but 2.5 -> 2
  423. ++number_.integral;
  424. }
  425. }
  426. return number_;
  427. }
  428. struct scaling_factor {
  429. double raw_factor;
  430. bool multiply; // if true, need to multiply by raw_factor; otherwise need
  431. // to divide by it
  432. };
  433. double apply_scaling(double num, struct scaling_factor normalization) {
  434. return normalization.multiply ? num * normalization.raw_factor
  435. : num / normalization.raw_factor;
  436. }
  437. double unapply_scaling(double normalized, struct scaling_factor normalization) {
  438. return normalization.multiply ? normalized / normalization.raw_factor
  439. : normalized * normalization.raw_factor;
  440. }
  441. struct scaling_factor update_normalization(struct scaling_factor sf,
  442. double extra_multiplicative_factor) {
  443. struct scaling_factor result;
  444. if (sf.multiply) {
  445. result.multiply = true;
  446. result.raw_factor = sf.raw_factor * extra_multiplicative_factor;
  447. } else {
  448. int factor_exp2 = get_exp2(get_bit_access(sf.raw_factor));
  449. int extra_factor_exp2 =
  450. get_exp2(get_bit_access(extra_multiplicative_factor));
  451. // Divide the larger-exponent raw raw_factor by the smaller
  452. if (PRINTF_ABS(factor_exp2) > PRINTF_ABS(extra_factor_exp2)) {
  453. result.multiply = false;
  454. result.raw_factor = sf.raw_factor / extra_multiplicative_factor;
  455. } else {
  456. result.multiply = true;
  457. result.raw_factor = extra_multiplicative_factor / sf.raw_factor;
  458. }
  459. }
  460. return result;
  461. }
  462. #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
  463. static struct double_components get_normalized_components(
  464. bool negative,
  465. unsigned int precision,
  466. double non_normalized,
  467. struct scaling_factor normalization) {
  468. struct double_components components;
  469. components.is_negative = negative;
  470. components.integral =
  471. (int_fast64_t)apply_scaling(non_normalized, normalization);
  472. double remainder =
  473. non_normalized -
  474. unapply_scaling((double)components.integral, normalization);
  475. double prec_power_of_10 = powers_of_10[precision];
  476. struct scaling_factor account_for_precision =
  477. update_normalization(normalization, prec_power_of_10);
  478. double scaled_remainder = apply_scaling(remainder, account_for_precision);
  479. double rounding_threshold = 0.5;
  480. if (precision == 0U) {
  481. components.fractional = 0;
  482. components.integral += (scaled_remainder >= rounding_threshold);
  483. if (scaled_remainder == rounding_threshold) {
  484. // banker's rounding: Round towards the even number (making the mean
  485. // error 0)
  486. components.integral &= ~((int_fast64_t)0x1);
  487. }
  488. } else {
  489. components.fractional = (int_fast64_t)scaled_remainder;
  490. scaled_remainder -= components.fractional;
  491. components.fractional += (scaled_remainder >= rounding_threshold);
  492. if (scaled_remainder == rounding_threshold) {
  493. // banker's rounding: Round towards the even number (making the mean
  494. // error 0)
  495. components.fractional &= ~((int_fast64_t)0x1);
  496. }
  497. // handle rollover, e.g. the case of 0.99 with precision 1 becoming
  498. // (0,100), and must then be corrected into (1, 0).
  499. if ((double)components.fractional >= prec_power_of_10) {
  500. components.fractional = 0;
  501. ++components.integral;
  502. }
  503. }
  504. return components;
  505. }
  506. #endif
  507. static size_t print_broken_up_decimal(struct double_components number_,
  508. out_fct_type out,
  509. char* buffer,
  510. size_t idx,
  511. size_t maxlen,
  512. unsigned int precision,
  513. unsigned int width,
  514. unsigned int flags,
  515. char* buf,
  516. size_t len) {
  517. if (precision != 0U) {
  518. // do fractional part, as an unsigned number
  519. unsigned int count = precision;
  520. if (flags & FLAGS_ADAPT_EXP && !(flags & FLAGS_HASH)) {
  521. // %g/%G mandates we skip the trailing 0 digits...
  522. if (number_.fractional > 0) {
  523. while (true) {
  524. int_fast64_t digit = number_.fractional % 10U;
  525. if (digit != 0) {
  526. break;
  527. }
  528. --count;
  529. number_.fractional /= 10U;
  530. }
  531. }
  532. // ... and even the decimal point if there are no
  533. // non-zero fractional part digits (see below)
  534. }
  535. if (number_.fractional > 0 || !(flags & FLAGS_ADAPT_EXP) ||
  536. (flags & FLAGS_HASH)) {
  537. while (len < PRINTF_FTOA_BUFFER_SIZE) {
  538. --count;
  539. buf[len++] = (char)('0' + number_.fractional % 10U);
  540. if (!(number_.fractional /= 10U)) {
  541. break;
  542. }
  543. }
  544. // add extra 0s
  545. while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
  546. buf[len++] = '0';
  547. }
  548. if (len < PRINTF_FTOA_BUFFER_SIZE) {
  549. buf[len++] = '.';
  550. }
  551. }
  552. } else {
  553. if (flags & FLAGS_HASH) {
  554. if (len < PRINTF_FTOA_BUFFER_SIZE) {
  555. buf[len++] = '.';
  556. }
  557. }
  558. }
  559. // Write the integer part of the number (it comes after the fractional
  560. // since the character order is reversed)
  561. while (len < PRINTF_FTOA_BUFFER_SIZE) {
  562. buf[len++] = (char)('0' + (number_.integral % 10));
  563. if (!(number_.integral /= 10)) {
  564. break;
  565. }
  566. }
  567. // pad leading zeros
  568. if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
  569. if (width &&
  570. (number_.is_negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
  571. width--;
  572. }
  573. while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
  574. buf[len++] = '0';
  575. }
  576. }
  577. if (len < PRINTF_FTOA_BUFFER_SIZE) {
  578. if (number_.is_negative) {
  579. buf[len++] = '-';
  580. } else if (flags & FLAGS_PLUS) {
  581. buf[len++] = '+'; // ignore the space if the '+' exists
  582. } else if (flags & FLAGS_SPACE) {
  583. buf[len++] = ' ';
  584. }
  585. }
  586. return out_rev_(out, buffer, idx, maxlen, buf, len, width, flags);
  587. }
  588. // internal ftoa for fixed decimal floating point
  589. static size_t print_decimal_number(out_fct_type out,
  590. char* buffer,
  591. size_t idx,
  592. size_t maxlen,
  593. double number,
  594. unsigned int precision,
  595. unsigned int width,
  596. unsigned int flags,
  597. char* buf,
  598. size_t len) {
  599. struct double_components value_ = get_components(number, precision);
  600. return print_broken_up_decimal(value_, out, buffer, idx, maxlen, precision,
  601. width, flags, buf, len);
  602. }
  603. #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
  604. // internal ftoa variant for exponential floating-point type, contributed by
  605. // Martijn Jasperse <m.jasperse@gmail.com>
  606. static size_t print_exponential_number(out_fct_type out,
  607. char* buffer,
  608. size_t idx,
  609. size_t maxlen,
  610. double number,
  611. unsigned int precision,
  612. unsigned int width,
  613. unsigned int flags,
  614. char* buf,
  615. size_t len) {
  616. const bool negative = get_sign(number);
  617. // This number will decrease gradually (by factors of 10) as we "extract"
  618. // the exponent out of it
  619. double abs_number = negative ? -number : number;
  620. int exp10;
  621. bool abs_exp10_covered_by_powers_table;
  622. struct scaling_factor normalization;
  623. // Determine the decimal exponent
  624. if (abs_number == 0.0) {
  625. // TODO: This is a special-case for 0.0 (and -0.0); but proper handling
  626. // is required for denormals more generally.
  627. exp10 = 0; // ... and no need to set a normalization factor or check
  628. // the powers table
  629. } else {
  630. double_with_bit_access conv = get_bit_access(abs_number);
  631. {
  632. // based on the algorithm by David Gay
  633. // (https://www.ampl.com/netlib/fp/dtoa.c)
  634. int exp2 = get_exp2(conv);
  635. // drop the exponent, so conv.F comes into the range [1,2)
  636. conv.U =
  637. (conv.U &
  638. (((double_uint_t)(1) << DOUBLE_STORED_MANTISSA_BITS) - 1U)) |
  639. ((double_uint_t)DOUBLE_BASE_EXPONENT
  640. << DOUBLE_STORED_MANTISSA_BITS);
  641. // now approximate log10 from the log2 integer part and an expansion
  642. // of ln around 1.5
  643. exp10 = (int)(0.1760912590558 + exp2 * 0.301029995663981 +
  644. (conv.F - 1.5) * 0.289529654602168);
  645. // now we want to compute 10^exp10 but we want to be sure it won't
  646. // overflow
  647. exp2 = (int)(exp10 * 3.321928094887362 + 0.5);
  648. const double z =
  649. exp10 * 2.302585092994046 - exp2 * 0.6931471805599453;
  650. const double z2 = z * z;
  651. conv.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT)
  652. << DOUBLE_STORED_MANTISSA_BITS;
  653. // compute exp(z) using continued fractions, see
  654. // https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
  655. conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
  656. // correct for rounding errors
  657. if (abs_number < conv.F) {
  658. exp10--;
  659. conv.F /= 10;
  660. }
  661. }
  662. abs_exp10_covered_by_powers_table =
  663. PRINTF_ABS(exp10) < PRINTF_MAX_PRECOMPUTED_POWER_OF_10;
  664. normalization.raw_factor = abs_exp10_covered_by_powers_table
  665. ? powers_of_10[PRINTF_ABS(exp10)]
  666. : conv.F;
  667. }
  668. // We now begin accounting for the widths of the two parts of our printed
  669. // field: the decimal part after decimal exponent extraction, and the
  670. // base-10 exponent part. For both of these, the value of 0 has a special
  671. // meaning, but not the same one: a 0 exponent-part width means "don't print
  672. // the exponent"; a 0 decimal-part width means "use as many characters as
  673. // necessary".
  674. bool fall_back_to_decimal_only_mode = false;
  675. if (flags & FLAGS_ADAPT_EXP) {
  676. int required_significant_digits = (precision == 0) ? 1 : (int)precision;
  677. // Should we want to fall-back to "%f" mode, and only print the decimal
  678. // part?
  679. fall_back_to_decimal_only_mode =
  680. (exp10 >= -4 && exp10 < required_significant_digits);
  681. // Now, let's adjust the precision
  682. // This also decided how we adjust the precision value - as in "%g"
  683. // mode, "precision" is the number of _significant digits_, and this is
  684. // when we "translate" the precision value to an actual number of
  685. // decimal digits.
  686. int precision_ =
  687. (fall_back_to_decimal_only_mode)
  688. ? (int)precision - 1 - exp10
  689. : (int)precision -
  690. 1; // the presence of the exponent ensures only one
  691. // significant digit comes before the decimal point
  692. precision = (precision_ > 0 ? (unsigned)precision_ : 0U);
  693. flags |= FLAGS_PRECISION; // make sure print_broken_up_decimal respects
  694. // our choice above
  695. }
  696. normalization.multiply = (exp10 < 0 && abs_exp10_covered_by_powers_table);
  697. bool should_skip_normalization =
  698. (fall_back_to_decimal_only_mode || exp10 == 0);
  699. struct double_components decimal_part_components =
  700. should_skip_normalization
  701. ? get_components(negative ? -abs_number : abs_number, precision)
  702. : get_normalized_components(negative, precision, abs_number,
  703. normalization);
  704. // Account for roll-over, e.g. rounding from 9.99 to 100.0 - which effects
  705. // the exponent and may require additional tweaking of the parts
  706. if (fall_back_to_decimal_only_mode) {
  707. if ((flags & FLAGS_ADAPT_EXP) && exp10 >= -1 &&
  708. decimal_part_components.integral == powers_of_10[exp10 + 1]) {
  709. exp10++; // Not strictly necessary, since exp10 is no longer really
  710. // used
  711. precision--;
  712. // ... and it should already be the case that
  713. // decimal_part_components.fractional == 0
  714. }
  715. // TODO: What about rollover strictly within the fractional part?
  716. } else {
  717. if (decimal_part_components.integral >= 10) {
  718. exp10++;
  719. decimal_part_components.integral = 1;
  720. decimal_part_components.fractional = 0;
  721. }
  722. }
  723. // the exp10 format is "E%+03d" and largest possible exp10 value for a
  724. // 64-bit double is "307" (for 2^1023), so we set aside 4-5 characters
  725. // overall
  726. unsigned int exp10_part_width = fall_back_to_decimal_only_mode ? 0U
  727. : (PRINTF_ABS(exp10) < 100) ? 4U
  728. : 5U;
  729. unsigned int decimal_part_width =
  730. ((flags & FLAGS_LEFT) && exp10_part_width)
  731. ?
  732. // We're padding on the right, so the width constraint is the
  733. // exponent part's problem, not the decimal part's, so we'll use as
  734. // many characters as we need:
  735. 0U
  736. :
  737. // We're padding on the left; so the width constraint is the decimal
  738. // part's problem. Well, can both the decimal part and the exponent
  739. // part fit within our overall width?
  740. ((width > exp10_part_width)
  741. ?
  742. // Yes, so we limit our decimal part's width.
  743. // (Note this is trivially valid even if we've fallen back to
  744. // "%f" mode)
  745. width - exp10_part_width
  746. :
  747. // No; we just give up on any restriction on the decimal part
  748. // and use as many characters as we need
  749. 0U);
  750. const size_t start_idx = idx;
  751. idx = print_broken_up_decimal(decimal_part_components, out, buffer, idx,
  752. maxlen, precision, decimal_part_width, flags,
  753. buf, len);
  754. if (!fall_back_to_decimal_only_mode) {
  755. out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
  756. idx = print_integer(out, buffer, idx, maxlen, ABS_FOR_PRINTING(exp10),
  757. exp10 < 0, 10, 0, exp10_part_width - 1,
  758. FLAGS_ZEROPAD | FLAGS_PLUS);
  759. if (flags & FLAGS_LEFT) {
  760. // We need to right-pad with spaces to meet the width requirement
  761. while (idx - start_idx < width)
  762. out(' ', buffer, idx++, maxlen);
  763. }
  764. }
  765. return idx;
  766. }
  767. #endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
  768. static size_t print_floating_point(out_fct_type out,
  769. char* buffer,
  770. size_t idx,
  771. size_t maxlen,
  772. double value,
  773. unsigned int precision,
  774. unsigned int width,
  775. unsigned int flags,
  776. bool prefer_exponential) {
  777. char buf[PRINTF_FTOA_BUFFER_SIZE];
  778. size_t len = 0U;
  779. // test for special values
  780. if (value != value)
  781. return out_rev_(out, buffer, idx, maxlen, "nan", 3, width, flags);
  782. if (value < -DBL_MAX)
  783. return out_rev_(out, buffer, idx, maxlen, "fni-", 4, width, flags);
  784. if (value > DBL_MAX)
  785. return out_rev_(out, buffer, idx, maxlen,
  786. (flags & FLAGS_PLUS) ? "fni+" : "fni",
  787. (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
  788. if (!prefer_exponential && ((value > PRINTF_FLOAT_NOTATION_THRESHOLD) ||
  789. (value < -PRINTF_FLOAT_NOTATION_THRESHOLD))) {
  790. // The required behavior of standard printf is to print _every_
  791. // integral-part digit -- which could mean printing hundreds of
  792. // characters, overflowing any fixed internal buffer and necessitating a
  793. // more complicated implementation.
  794. #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
  795. return print_exponential_number(out, buffer, idx, maxlen, value,
  796. precision, width, flags, buf, len);
  797. #else
  798. return 0U;
  799. #endif
  800. }
  801. // set default precision, if not set explicitly
  802. if (!(flags & FLAGS_PRECISION)) {
  803. precision = PRINTF_DEFAULT_FLOAT_PRECISION;
  804. }
  805. // limit precision so that our integer holding the fractional part does not
  806. // overflow
  807. while ((len < PRINTF_FTOA_BUFFER_SIZE) &&
  808. (precision > PRINTF_MAX_SUPPORTED_PRECISION)) {
  809. buf[len++] =
  810. '0'; // This respects the precision in terms of result length only
  811. precision--;
  812. }
  813. return
  814. #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
  815. prefer_exponential
  816. ? print_exponential_number(out, buffer, idx, maxlen, value,
  817. precision, width, flags, buf, len)
  818. :
  819. #endif
  820. print_decimal_number(out, buffer, idx, maxlen, value, precision,
  821. width, flags, buf, len);
  822. }
  823. #endif // (PRINTF_SUPPORT_DECIMAL_SPECIFIERS ||
  824. // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS)
  825. // internal vsnprintf
  826. static int __vsnprintf(out_fct_type out,
  827. char* buffer,
  828. const size_t maxlen,
  829. const char* format,
  830. va_list va) {
  831. unsigned int flags, width, precision, n;
  832. size_t idx = 0U;
  833. if (!buffer) {
  834. // use null output function
  835. out = out_discard;
  836. }
  837. while (*format) {
  838. // format specifier? %[flags][width][.precision][length]
  839. if (*format != '%') {
  840. // no
  841. out(*format, buffer, idx++, maxlen);
  842. format++;
  843. continue;
  844. } else {
  845. // yes, evaluate it
  846. format++;
  847. }
  848. // evaluate flags
  849. flags = 0U;
  850. do {
  851. switch (*format) {
  852. case '0':
  853. flags |= FLAGS_ZEROPAD;
  854. format++;
  855. n = 1U;
  856. break;
  857. case '-':
  858. flags |= FLAGS_LEFT;
  859. format++;
  860. n = 1U;
  861. break;
  862. case '+':
  863. flags |= FLAGS_PLUS;
  864. format++;
  865. n = 1U;
  866. break;
  867. case ' ':
  868. flags |= FLAGS_SPACE;
  869. format++;
  870. n = 1U;
  871. break;
  872. case '#':
  873. flags |= FLAGS_HASH;
  874. format++;
  875. n = 1U;
  876. break;
  877. default:
  878. n = 0U;
  879. break;
  880. }
  881. } while (n);
  882. // evaluate width field
  883. width = 0U;
  884. if (is_digit_(*format)) {
  885. width = atoi_(&format);
  886. } else if (*format == '*') {
  887. const int w = va_arg(va, int);
  888. if (w < 0) {
  889. flags |= FLAGS_LEFT; // reverse padding
  890. width = (unsigned int)-w;
  891. } else {
  892. width = (unsigned int)w;
  893. }
  894. format++;
  895. }
  896. // evaluate precision field
  897. precision = 0U;
  898. if (*format == '.') {
  899. flags |= FLAGS_PRECISION;
  900. format++;
  901. if (is_digit_(*format)) {
  902. precision = atoi_(&format);
  903. } else if (*format == '*') {
  904. const int precision_ = (int)va_arg(va, int);
  905. precision = precision_ > 0 ? (unsigned int)precision_ : 0U;
  906. format++;
  907. }
  908. }
  909. // evaluate length field
  910. switch (*format) {
  911. case 'l':
  912. flags |= FLAGS_LONG;
  913. format++;
  914. if (*format == 'l') {
  915. flags |= FLAGS_LONG_LONG;
  916. format++;
  917. }
  918. break;
  919. case 'h':
  920. flags |= FLAGS_SHORT;
  921. format++;
  922. if (*format == 'h') {
  923. flags |= FLAGS_CHAR;
  924. format++;
  925. }
  926. break;
  927. case 't':
  928. flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG
  929. : FLAGS_LONG_LONG);
  930. format++;
  931. break;
  932. case 'j':
  933. flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG
  934. : FLAGS_LONG_LONG);
  935. format++;
  936. break;
  937. case 'z':
  938. flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG
  939. : FLAGS_LONG_LONG);
  940. format++;
  941. break;
  942. default:
  943. break;
  944. }
  945. // evaluate specifier
  946. switch (*format) {
  947. case 'd':
  948. case 'i':
  949. case 'u':
  950. case 'x':
  951. case 'X':
  952. case 'o':
  953. case 'b': {
  954. // set the base
  955. numeric_base_t base;
  956. if (*format == 'x' || *format == 'X') {
  957. base = BASE_HEX;
  958. } else if (*format == 'o') {
  959. base = BASE_OCTAL;
  960. } else if (*format == 'b') {
  961. base = BASE_BINARY;
  962. } else {
  963. base = BASE_DECIMAL;
  964. flags &= ~FLAGS_HASH; // no hash for dec format
  965. }
  966. // uppercase
  967. if (*format == 'X') {
  968. flags |= FLAGS_UPPERCASE;
  969. }
  970. // no plus or space flag for u, x, X, o, b
  971. if ((*format != 'i') && (*format != 'd')) {
  972. flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
  973. }
  974. // ignore '0' flag when precision is given
  975. if (flags & FLAGS_PRECISION) {
  976. flags &= ~FLAGS_ZEROPAD;
  977. }
  978. // convert the integer
  979. if ((*format == 'i') || (*format == 'd')) {
  980. // signed
  981. if (flags & FLAGS_LONG_LONG) {
  982. #if PRINTF_SUPPORT_LONG_LONG
  983. const long long value = va_arg(va, long long);
  984. idx = print_integer(out, buffer, idx, maxlen,
  985. ABS_FOR_PRINTING(value), value < 0,
  986. base, precision, width, flags);
  987. #endif
  988. } else if (flags & FLAGS_LONG) {
  989. const long value = va_arg(va, long);
  990. idx = print_integer(out, buffer, idx, maxlen,
  991. ABS_FOR_PRINTING(value), value < 0,
  992. base, precision, width, flags);
  993. } else {
  994. const int value =
  995. (flags & FLAGS_CHAR) ? (signed char)va_arg(va, int)
  996. : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int)
  997. : va_arg(va, int);
  998. idx = print_integer(out, buffer, idx, maxlen,
  999. ABS_FOR_PRINTING(value), value < 0,
  1000. base, precision, width, flags);
  1001. }
  1002. } else {
  1003. // unsigned
  1004. if (flags & FLAGS_LONG_LONG) {
  1005. #if PRINTF_SUPPORT_LONG_LONG
  1006. idx =
  1007. print_integer(out, buffer, idx, maxlen,
  1008. (printf_unsigned_value_t)va_arg(
  1009. va, unsigned long long),
  1010. false, base, precision, width, flags);
  1011. #endif
  1012. } else if (flags & FLAGS_LONG) {
  1013. idx = print_integer(
  1014. out, buffer, idx, maxlen,
  1015. (printf_unsigned_value_t)va_arg(va, unsigned long),
  1016. false, base, precision, width, flags);
  1017. } else {
  1018. const unsigned int value =
  1019. (flags & FLAGS_CHAR)
  1020. ? (unsigned char)va_arg(va, unsigned int)
  1021. : (flags & FLAGS_SHORT)
  1022. ? (unsigned short int)va_arg(va, unsigned int)
  1023. : va_arg(va, unsigned int);
  1024. idx =
  1025. print_integer(out, buffer, idx, maxlen,
  1026. (printf_unsigned_value_t)value, false,
  1027. base, precision, width, flags);
  1028. }
  1029. }
  1030. format++;
  1031. break;
  1032. }
  1033. #if PRINTF_SUPPORT_DECIMAL_SPECIFIERS
  1034. case 'f':
  1035. case 'F':
  1036. if (*format == 'F')
  1037. flags |= FLAGS_UPPERCASE;
  1038. idx = print_floating_point(out, buffer, idx, maxlen,
  1039. va_arg(va, double), precision, width,
  1040. flags, PRINTF_PREFER_DECIMAL);
  1041. format++;
  1042. break;
  1043. #endif
  1044. #if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
  1045. case 'e':
  1046. case 'E':
  1047. case 'g':
  1048. case 'G':
  1049. if ((*format == 'g') || (*format == 'G'))
  1050. flags |= FLAGS_ADAPT_EXP;
  1051. if ((*format == 'E') || (*format == 'G'))
  1052. flags |= FLAGS_UPPERCASE;
  1053. idx = print_floating_point(out, buffer, idx, maxlen,
  1054. va_arg(va, double), precision, width,
  1055. flags, PRINTF_PREFER_EXPONENTIAL);
  1056. format++;
  1057. break;
  1058. #endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
  1059. case 'c': {
  1060. unsigned int l = 1U;
  1061. // pre padding
  1062. if (!(flags & FLAGS_LEFT)) {
  1063. while (l++ < width) {
  1064. out(' ', buffer, idx++, maxlen);
  1065. }
  1066. }
  1067. // char output
  1068. out((char)va_arg(va, int), buffer, idx++, maxlen);
  1069. // post padding
  1070. if (flags & FLAGS_LEFT) {
  1071. while (l++ < width) {
  1072. out(' ', buffer, idx++, maxlen);
  1073. }
  1074. }
  1075. format++;
  1076. break;
  1077. }
  1078. case 's': {
  1079. const char* p = va_arg(va, char*);
  1080. if (p == NULL) {
  1081. idx = out_rev_(out, buffer, idx, maxlen, ")llun(", 6, width,
  1082. flags);
  1083. } else {
  1084. unsigned int l =
  1085. strnlen_s_(p, precision ? precision : (size_t)-1);
  1086. // pre padding
  1087. if (flags & FLAGS_PRECISION) {
  1088. l = (l < precision ? l : precision);
  1089. }
  1090. if (!(flags & FLAGS_LEFT)) {
  1091. while (l++ < width) {
  1092. out(' ', buffer, idx++, maxlen);
  1093. }
  1094. }
  1095. // string output
  1096. while ((*p != 0) &&
  1097. (!(flags & FLAGS_PRECISION) || precision--)) {
  1098. out(*(p++), buffer, idx++, maxlen);
  1099. }
  1100. // post padding
  1101. if (flags & FLAGS_LEFT) {
  1102. while (l++ < width) {
  1103. out(' ', buffer, idx++, maxlen);
  1104. }
  1105. }
  1106. }
  1107. format++;
  1108. break;
  1109. }
  1110. case 'p': {
  1111. width = sizeof(void*) * 2U +
  1112. 2; // 2 hex chars per byte + the "0x" prefix
  1113. flags |= FLAGS_ZEROPAD | FLAGS_POINTER;
  1114. uintptr_t value = (uintptr_t)va_arg(va, void*);
  1115. idx = (value == (uintptr_t)NULL)
  1116. ? out_rev_(out, buffer, idx, maxlen, ")lin(", 5,
  1117. width, flags)
  1118. : print_integer(out, buffer, idx, maxlen,
  1119. (printf_unsigned_value_t)value, false,
  1120. BASE_HEX, precision, width, flags);
  1121. format++;
  1122. break;
  1123. }
  1124. case '%':
  1125. out('%', buffer, idx++, maxlen);
  1126. format++;
  1127. break;
  1128. default:
  1129. out(*format, buffer, idx++, maxlen);
  1130. format++;
  1131. break;
  1132. }
  1133. }
  1134. // termination
  1135. out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
  1136. // return written chars without terminating \0
  1137. return (int)idx;
  1138. }
  1139. /**
  1140. * This function will fill a formatted string to buffer.
  1141. *
  1142. * @param buf is the buffer to save formatted string.
  1143. *
  1144. * @param size is the size of buffer.
  1145. *
  1146. * @param fmt is the format parameters.
  1147. *
  1148. * @param args is a list of variable parameters.
  1149. *
  1150. * @return The number of characters actually written to buffer.
  1151. */
  1152. int pika_platform_vsnprintf(char* buff,
  1153. size_t size,
  1154. const char* fmt,
  1155. va_list args) {
  1156. return __vsnprintf(out_buffer, buff, size, fmt, args);
  1157. }