An open API service indexing awesome lists of open source software.

https://github.com/iokg04/cfmt

sprintf() like formatting entirely in zig - sometimes std.fmt is just too weak
https://github.com/iokg04/cfmt

formatting sprintf-style zig

Last synced: 11 months ago
JSON representation

sprintf() like formatting entirely in zig - sometimes std.fmt is just too weak

Awesome Lists containing this project

README

          

# cfmt

Zig's `@import("std").fmt` may be good, but in some cases you just need a little bit more functionality.

Now why not just link in `libc` and use `sprintf()` and such?

Either because you are on some device where there isn't (yet) a `libc` to link against,
because you just don't *want* to link against `libc`,
or lastly because you're using some types c doesn't understand (`u19`, `f128`, etc.) and want a native zig solution.

That being said, this is not a drop in replacement, the format specifiers are a little different from c's.
I did design them to be as close as possible though, requiring little rethinking if you're already used to c.

A lot of what's written here isn't implemented yet, I am working on it though.
Also any ideas are appreciated, making this more feature rich would be nice :3

Also also, I will add a `build.zig.zon` once this can be reasonably used as a library.
Might even make it so you can compile it to a static/dynamic library to use with other languages.

## Format specifier

Format specifiers in `cfmt` look something like this:
```zig
"%s" // a string
"%.4f" // a floating-point value rounded to 4 digits after the period
"%-4.8i" // a left alligned integer of at least 4 and at most 8 digits
```

They can be split into five parts in this exact order:
A `%` character,
[flags](#flags),
[minimum width](#minimum-width),
[precision](#precision) and lastly
the [specifier](#specifiers).

All besides the specifier are optional.

The only exception to this is the specifier for writing a `%` character, which is `%%`.

### Specifiers

Specifiers tell `cfmt` what kind of type you're formatting and how you want it formatted.

The following specifiers exist:

**Integers:**
- `i`: Decimal integer
- `b`: Binary integer
- `o`: Octal integer
- `x`: Hexadecimal integer (lowercase)
- `X`: Hexadecimal integer (uppercase)

**Floating-point:**
- `f`: Decimal floating-point

**Other:**
- `s`: String
- `c`: Character
- `p`: Pointer (hexadecimal lowercase)
- `P`: Pointer (hexadecimal uppercase)

**Special:**

\*cricket noises\*

For better compatibility with c's format specifiers, `d` and `u` work the same as `i`.

### Minimum width

If a minimum width is specified and the formatted string isn't that long, the string will be padded with space characters.

The minimum width can either be a decimal number, such as `4`, `9` or `142`,
or a `*`, in which case an `usize` is read from the arguments and its value is used as the minimum width.

If a `*` is used, the dynamic minimum width must be given before the value to be formatted (and the dynamic precision if used).

Please note that the decimal number may not have a leading zero as that could interfere with the [`0` flag](#flags).

By default, the formatted contents will be right alligned (space characters on the left),
though this behavior can be changed with the [`-` flag](#flags).

### Precision

What exactly *precision* means depends on the type to be formatted:

If it's a floating point value, precision is the amount of digits after the decimal separator.

If it's a string, precision defines the maximum amount of characters written.
When truncation happens, the last characters are cut off.

If it's a character, it will be repeated *precision* times.
Does it make sense to call that precision? No.
Could it still be a useful functionality? Yes.

For any other type, precision doesn't do anything.

To set the precision, a `.` followed by a number or a `*` is used, similar to [minimum width](#minimum-width) except with a `.` character.

Here however, the precision is put *between* the dynamic minimum width and value to be formatted.

If neither a `*` or a number follows the `.`, precision is set to `0`.

### Flags

Flags change some parts of formatting.

The following flags exist:
- `-`: Allign to the left instead of right (space characters on the right)
- `+`: Always write `+` and `-` sign for numeric types
- ` `: (space) Write a space character at start of positive numeric values
- `<`: Write sign before any padding
- `0`: Pad with `0` characters instead of space characters