Skip to content

settings.toml: parse integers with our own routine instead of strtol() - #66

Merged
mikeysklar merged 1 commit into
mikeysklar:settings-toml-leading-zerofrom
dhalbert:settings-toml-int-parser
Oct 17, 2026
Merged

mikeysklar merged 1 commit into
mikeysklar:settings-toml-leading-zerofrom
dhalbert:settings-toml-int-parser

Conversation

@dhalbert

Copy link
Copy Markdown

PR note written by @dhalbert. Claude wrote the code. @mikeysklar, for your consideration.

We were using strtol() to parse integers and strtoul() to parse \u escapes. strtol() doesn't handle underscores, and nothing else in the firmware uses it. strtoul() is only used elsewhere by the web workflow.

If we replace both with our own routine, we can support more features, and in less space. The new routine is parse_digits(). Sign, prefix, and range handling are done in get_int(). The new code handles 0o, 0b, 0O, and 0B, allows underscores, and still prevents leading zeros, the point of the original PR. It also doesn't clamp out-of-range values to LONG_MAX: a too-big hex, octal, or binary value raises ValueError, and a too-big decimal value comes back as a float. It's more relaxed than the TOML spec at some things.

It passes tests/circuitpython-manual/settings on a Metro M4 Express and the unix coverage make test.

Size

Board Flash RAM
ItsyBitsy nRF52840 Express −660 −80
Feather RP2040 −620 0

Replace strtol() in get_int() and strtoul() in read_unicode_escape()
with a small digit parser. This drops strtol, strtoul, _ctype_, errno
and _impure_data from the link: -660 bytes flash and -80 bytes RAM on
the ItsyBitsy nRF52840, -620 bytes flash on the Feather RP2040.

Integers now also accept 0o and 0b prefixes and underscores (1_000).
As a superset of TOML, a sign is allowed before 0x/0o/0b, the prefix
may be uppercase, and underscores are not checked to be between digits.

Out-of-range integers are no longer clamped to LONG_MAX.
settings_get_int() returns an error for them; supervisor.get_setting()
raises ValueError for hex, octal and binary, and returns a float for
decimal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mikeysklar
mikeysklar merged commit 56b5053 into mikeysklar:settings-toml-leading-zero Oct 17, 2026
@mikeysklar

mikeysklar commented Oct 17, 2026 •

Copy link
Copy Markdown
Owner

Thanks Dan, merged into the adafruit#11620 branch.

Sizes measured on the same tree with and without your commit.

The savings are substantial as you claimed on nRF / RP2. ESP32-S3 takes a smaller hit.

Board Flash RAM Why
ItsyBitsy nRF52840 -676 -80 strtol, strtoul, _ctype_, errno all drop
Feather nRF52840 -660 -80 same
Metro RP2040 -620 0 errno stays
Metro RP2350 -296 0 _ctype_ stays, used by strcasecmp
Metro M0 0 0 settings.toml compiled out
Metro ESP32-S3 +220 0 strtoul stays, used by web workflow and mdns

It also adds two bugs:

settings.toml before now
12@ ValueError 129
"\u0_41" ValueError "A"

In parse_digits(), @ and ` wrap around to the digit 9.

The \u escape skips _.

I'll push fixes for both to adafruit#11620, with tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants