Skip to content

About

πŸ”’ An extensible sprintf function supporting stdarg and mulle-vararg

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Repository files navigation

mulle-sprintf

πŸ”’ An extensible sprintf function supporting stdarg and mulle-vararg

mulle-sprintf is a fast, extensible C formatting library for projects that need more than a basic sprintf . It supports standard stdarg and mulle_vararg calls, custom conversion handlers, UTF-8/UTF-16/UTF-32 strings, allocator-aware buffers, integer and floating-point formatting, and convenient sprintf / snprintf / asprintf -style APIs. Designed for the Mulle ecosystem but useful on its own, it combines familiar C formatting with a modular architecture, focused performance optimizations, and clear extension points for application-specific types and output formats.

The extensibility is used in MulleObjCStandardFoundation to add object conversion (%@) and to print BOOL values as 'YES', 'NO' (%bd).

Floating point conversion is done by mulle-dtostr, but fallback to C library FP can be used with NO_MULLE__DTOSTR. long double arguments are cast to double before formatting.

Performance

Release benchmark, 100,000 iterations on linux:

Case mulle glibc Ratio
int %d 6.438 ms 4.211 ms 1.53x
int %d x3 12.698 ms 10.798 ms 1.18x
int %d x16 59.206 ms 51.998 ms 1.14x
int %d x24 88.304 ms 76.374 ms 1.16x
long lit + %d 9.549 ms 3.038 ms 3.14x
literal %% + long tail + %d 14.429 ms 6.441 ms 2.24x
hex %x 6.635 ms 4.354 ms 1.52x
hex %x x8 32.187 ms 27.136 ms 1.19x
oct %o 6.714 ms 4.399 ms 1.53x
oct %o x8 33.519 ms 26.976 ms 1.24x
mixed 8 conversions 53.597 ms 51.750 ms 1.04x
float %.6f x3 46.727 ms 52.136 ms 0.90x
float %.6f x16 226.419 ms 286.144 ms 0.79x
float %.6f x24 349.513 ms 424.260 ms 0.82x
string %s + int x2 9.919 ms 7.170 ms 1.38x
string %s x8 23.267 ms 18.597 ms 1.25x
string %s x24 71.808 ms 52.602 ms 1.37x
pad mix (12 conversions) 88.649 ms 101.189 ms 0.88x
Release Version Release Notes AI Documentation
Mulle kybernetiK tag Build Status RELEASENOTES DeepWiki for mulle-sprintf

API

File Description
mulle_sprintf The various sprintf like functions

Major stdlib-compatible functions

Function Description
mulle_sprintf sprintf replacement
mulle_snprintf snprintf replacement
mulle_asprintf asprintf replacement
mulle_buffer_sprintf sprintf into mulle_buffer
mulle_allocator_asprintf asprintf with custom allocator

Format characters

For more detailed information on each characte consult a sprintf man page.

Flag Characters

Character Description
Β  (SPC) A blank should be left before a positive number.
0 The value should be zero padded.
# The value should be converted to an "alternate form".
- The converted value is to be left adjusted on the field boundary.
+ A sign (+ or -) should always be placed before a number.
' Use thousands' grouping characters (UNUSED)
b BOOL, print as YES or NO (for Objective-C)

Length modifier

Characters Description
h short (or utf16)
hh char (or utf8)
j intmax_t
l long (or utf32)
ll long long
L long double (FP only)
q int64.
t ptrdiff_t
z size_t

Conversion Specifiers (built in)

Integer

Character Description
i int as decimal
d int as decimal
D long int (compatibility)
u unsigned int
o int as octal
x int as lowercase hex
U unsigned long int (compatibility)
O unsigned long int as octal (compatibility)
X unsigned long int as hex (compatibility)

Used modifiers: all except L

Floating Point (FP)

Uppercase conversion specifiers output value such as 0e-20 or nan as uppercase 0E-20 or NAN.

Character Description
a double as hex [-]0xh.hhhhp+-d
e double as [-]d.ddde+-dd
f double as [-]ddd.ddd with lowercase for inf/nan
g double in e or f
A double as hex [-]0Xh.hhhhP+-d
E double as [-]d.dddE+-dd
F double as [-]d.ddde+-dd with uppercase for INF/NAN
G double in E or F

Used modifiers: L.

The actual conversion is done with the C-library sprintf function. This is contrast with the other conversions, which are not using the C library. For portability across platforms -nan and -0.0 will not be printed with the leading minus sign.

Pointer / String / Other

Character Description
c single character
C wide character (utf16 with h, utf32 with l or no modifier)
n return conversion
p void * as hex with 0x prefix
s char * as utf8 (alternate form #s: escaped for C String)
S wide string (utf16 with h, utf32 with l or no modifier, utf8 with hh)

Used modifiers: hl

Character and String Format Specifiers

mulle-sprintf provides two sets of character and string format specifiers:

Lowercase (C Standard Compatible - Platform Dependent)

These follow the C standard and use platform-dependent wide character types:

%c - Character:

  • %c: char (single byte character)
  • %lc: wint_t (wide character, platform-dependent encoding)

%s - String:

  • %s: char * (null-terminated UTF-8/ASCII string)
  • %ls: wchar_t * (wide string, platform-dependent encoding)
    • Windows: UTF-16 (wchar_t is 16-bit)
    • Linux/Unix: UTF-32 (wchar_t is 32-bit)

Use these when working with C standard library functions or platform APIs that expect wchar_t.

Uppercase (Explicit UTF Encoding - Platform Independent)

These provide explicit UTF encoding control, avoiding platform-dependent wchar_t:

%C - Wide Character:

  • %C or %lC: uint32_t (UTF-32 codepoint, explicit 32-bit)
  • %hC: uint16_t (UTF-16 code unit, explicit 16-bit)

%S - Wide String:

  • %S or %lS: uint32_t * (UTF-32 string, explicit 32-bit per character)
  • %hS: uint16_t * (UTF-16 string, explicit 16-bit per character)
  • %hhS: char * (UTF-8 string, same as %s)

Use these when you need guaranteed UTF encoding regardless of platform.

Key Differences:

Format Type Encoding Platform Dependent?
%ls wchar_t * UTF-16 (Windows) / UTF-32 (Unix) Yes
%lS uint32_t * UTF-32 always No
%lc wint_t UTF-16 (Windows) / UTF-32 (Unix) Yes
%lC uint32_t UTF-32 always No

Example:

// Platform-dependent (C standard)
wchar_t *wstr = L"Hello";
mulle_sprintf(buf, "%ls", wstr);  // Uses wchar_t encoding

// Platform-independent (explicit UTF-32)
uint32_t utf32_str[] = {'H', 'e', 'l', 'l', 'o', 0};
mulle_sprintf(buf, "%lS", utf32_str);  // Always UTF-32
mulle_sprintf(buf, "%S", utf32_str);   // Same as %lS

Documentation & Guides

Usage

mulle-sprintf provides stdlib-compatible functions that work out of the box:

char buf[ 32];

mulle_snprintf( buf, sizeof( buf), "%d", 1848);
char *str;

mulle_asprintf( &str, "%s %d", "VfL", 1848);
mulle_free( str);
mulle_buffer_do( buffer)
{
    mulle_buffer_sprintf( buffer, "%d", 1848);
}

You are here

Overview

Add

mulle-sprintf is a component of the mulle-core library. So in your code include the mulle-core umbrella header:

#include <mulle-core/mulle-core.h>

Add mulle-core to a cmake and git project

git submodule add https://github.com/mulle-core/mulle-core.git mulle-core

Add this to your CMakeLists.txt:

add_subdirectory( mulle-core)
target_link_libraries( ${PROJECT_NAME} PRIVATE mulle-core)

Add mulle-core to a mulle-sde project

mulle-sde add github:mulle-core/mulle-core

Embed mulle-sprintf with clib

clib install --out src mulle-core/mulle-sprintf

Append src to your include path (e.g. add -isystem src to your CFLAGS) and compile all the sources that were downloaded.

Install

Use mulle-sde to build and install mulle-sprintf and all dependencies:

mulle-sde install --prefix /usr/local \
   https://github.com/mulle-core/mulle-sprintf/archive/latest.tar.gz

Legacy Installation

Install the requirements:

Requirements Description
mulle-buffer ↗️ A growable C char array and also a stream - on stack and heap
mulle-utf πŸ”€ UTF8-16-32 analysis and manipulation library
mulle-vararg βͺ Access variable arguments in struct layout fashion in C
mulle-thread πŸ”  Cross-platform thread/mutex/tss/atomic operations in C
mulle-dtostr 🧢 Double to string conversion

Download the latest tar or zip archive and unpack it.

Install mulle-sprintf into /usr/local with cmake:

PREFIX_DIR="/usr/local"
cmake -B build                               \
      -DMULLE_SDK_PATH="${PREFIX_DIR}"       \
      -DCMAKE_INSTALL_PREFIX="${PREFIX_DIR}" \
      -DCMAKE_PREFIX_PATH="${PREFIX_DIR}"    \
      -DCMAKE_BUILD_TYPE=Release &&
cmake --build build --config Release &&
cmake --install build --config Release

Author

Nat! for Mulle kybernetiK

About

πŸ”’ An extensible sprintf function supporting stdarg and mulle-vararg

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages