strtonum(3bsd)

πŸ“¦
version 0.12.2 Β· 3 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, debian trixie, epel 10, epel 9, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

✨ strtonum ✨

okay bestie, welcome to strtonum from the 3bsd section β€” she's a lil utility function, and she's here to reliably convert a string value to an integer. no cap. this is the glow-up version of all those messy atoi situations you've been dealing with πŸ’…


πŸŽ€ LIBRARY

Utility functions from BSD systems, and you link her in with libbsd / -lbsd. periodt.


πŸ“œ SYNOPSIS

#include <limits.h>
#include <stdlib.h>
(See libbsd(7) for include usage.)

long long
strtonum(const char *nptr, long long minval, long long maxval,
    const char **errstr);
btw if you're confused about the include situation, go read libbsd(7), she explains the whole thing 🫢

πŸ’– DESCRIPTION

So strtonum() takes the string sitting in nptr and turns it into a long long value. simple as that, fr fr.

The string is allowed to start with however much whitespace it wants β€” and "whitespace" here means whatever isspace(3) says counts, bestie, not just your vibe-based guess 🌸 β€” and after all that space it can have one single optional '+' or '-' sign. one. single. not two.

Everything left after that gets converted to a long long value according to base 10. base 10 only, she's not doing the whole hex thing, don't ask.

Then β€” and this is the iconic part β€” that value gets checked against the bounds you handed her, minval and maxval. And if errstr isn't null, strtonum() will store an error string into *errstr to tell you what went wrong 😭


πŸ”₯ RETURN VALUES

strtonum() gives you back the result of the conversion... unless the value would blow past the bounds you gave her, or it's just straight up invalid.

When there's an error: she returns 0, sets errno, and errstr points at an error message. 🫠

When it's a success: *errstr gets set to NULL. and honestly that's the little trick that matters β€” because that's literally how you tell apart a legit successful return of 0 from an error that returned 0. same zero, different lore. iykyk.


🌈 EXAMPLES

Using strtonum() the right way is meant to be simpler than the other options out there. and like... look at her:

int iterations;
const char *errstr;

iterations = strtonum(optarg, 1, 64, &errstr);
if (errstr)
        errx(1, "number of iterations is %s: %s", errstr, optarg);

and what this guarantees is that iterations is somewhere between 1 and 64, inclusive. no sneaky out-of-range values slipping through, we love a safety queen πŸ‘‘


πŸ’€ ERRORS

  • [EINVAL] β€” the string you gave her wasn't made up solely of digit characters; or minval was bigger than maxval. yeah that second one is on you bestie πŸ™ˆ
  • [ERANGE] β€” the string was out of range.

If an error happens, errstr gets set to one of these strings:

  • too large β€” the result was larger than the maximum value you provided.
  • too small β€” the result was smaller than the minimum value you provided.
  • invalid β€” the string didn't consist solely of digit characters.

πŸ¦‹ SEE ALSO

atof(3), atoi(3), atol(3), atoll(3), sscanf(3), strtod(3), strtoi(3bsd), strtol(3), strtoll(3), strtou(3bsd), strtoul(3), strtoull(3)

go read the whole friend group, they all have their own drama πŸ’œ


⭐ STANDARDS

strtonum() is a BSD extension. she's not standard C, she's a special girl.


🧚 HISTORY

strtonum() first appeared in OpenBSD 3.6. then she got a whole redesign in NetBSD 8.0, where she came back as strtoi(3bsd) and strtou(3bsd). glow-up arc, honestly iconic ✨


πŸ™ˆ CAVEATS

okay so real talk. strtonum() was designed to make safe, robust programming easier and to fix all the shortcomings of the atoi(3) and strtol(3) family of interfaces. BUT β€” and this is the part nobody puts in the group chat β€” there are actual problems with the strtonum() API:

  • will return 0 on failure; and 0 might not even be in range, so that forces you to do an error check even when you were trying to avoid one 😭
  • does not differentiate 'illegal' returns, so we can't tell the difference between partial and no conversions
  • returns english strings
  • can't set the base, or find where the conversion ended
  • hardcodes long long integer type

and to overcome all of those shortcomings of strtonum(), NetBSD provides strtou(3bsd) and strtoi(3bsd). so if these caveats are giving you the ick, you know where to go 🫢


and that's the whole page, bestie!! this one's from the Debian crew, dated January 18, 2015, and she goes by strtonum(3bsd) πŸ’…βœ¨ stay safe, check your errstr, mwah πŸŽ€

πŸ“¦ where this page comes from