Skip to content

libwcwidth, a portable C11 library - #247

Merged
jquast merged 12 commits into
masterfrom
jq/libwcwidth-rc
Sep 15, 2026
Merged

jquast merged 12 commits into
masterfrom
jq/libwcwidth-rc

Conversation

@jquast

@jquast jquast commented Sep 15, 2026 •

Copy link
Copy Markdown
Owner

Adds sub-folder to this project, libwcwidth/, a C11 implementation of the wcwidth API. This is a release candidate, relased by git tags on github along with matching version of python wcwidth, but not yet included as a Python C extension, this code is not distributed by pypi.

#248 creates the C Python "shims" to join the projects together.

Note that the C tables are generated from the Unicode 18.0.0 (draft), 18.0 is expected to release later today, so we intend for these to match before any next python release or git version tag.

@codecov

codecov Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (f7b9df5) to head (cfdefbe).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##            master      #247   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           27        27           
  Lines         2004      2004           
  Branches       469       469           
=========================================
  Hits          2004      2004           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codspeed

codspeed Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 116 untouched benchmarks


Comparing jq/libwcwidth-rc (cfdefbe) with master (f7b9df5)

Open in CodSpeed

The C11 library rides in the git tags only for now.  The sdist include
returns with the Python C extension, which needs the sources to build.
@jquast
jquast added this pull request to stack #249 September 15, 2026 13:18
@jquast

jquast commented Sep 15, 2026 •

Copy link
Copy Markdown
Owner Author

I intend to push some improvements to this PR to use bitsets for some tables instead of bisearch. I previously experimented with this in python but it consumed too much memory, but we should get 2 or 3x improvement for 100KB or so of memory.

Improvement was only up to 1.2x with WIDE and other "hot path" tables, with more tables for diminishing returns, code is too complex, i will however use similar technique to improve grapheme iteration by ~2x

gcb_of() classified every codepoint with a chain of up to ten sequential binary
searches, and GCB_OTHER -- the common ASCII and Latin case -- paid all ten.  It
is the hottest loop in the library, driven per codepoint by grapheme iteration,
clip() and wrap().

The classes are disjoint under that precedence order, so they pack into a single
nibble-per-codepoint table and one lookup replaces the chain.  update-tables.py
picks the page size by measuring, so the table is re-costed on each regeneration.

Grapheme iteration is 2-2.4x faster, for 15 KB of rodata.
tests/test_gcb_class.c checks the table against the chain it replaces for every
codepoint, and against the Extend table, which terminal_override.c relied on
directly.

Also fixes the Makefile 'test' recipe: $(foreach) joins its expansions with a
space, so each test binary was invoked with the following '@echo' as its
arguments and only the first header was ever printed.
The version is read from the generated wcwidth_config.h, but the regex required
MAJOR.MINOR.PATCH followed immediately by the closing quote.  A PEP 440
pre-release such as '0.9.0rc1' did not match, the replace returned the whole
#define line unchanged, and project() rejected it -- breaking the cmake build
and the ctest CI step.
Add clang_format and clang_format_check tox envs, wired into 'format' and
'lint', and add the check to the CI lint matrix.  The hand-written C was never
fully formatted, so this reformats it in the same commit.

Generated tables under src/tables are excluded from the format targets; their
layout comes from the templates, and formatting them would fight every
regeneration.
Comment thread bin/update-docs.py Fixed
@jquast
jquast merged commit 85cc473 into master Sep 15, 2026
34 checks passed
@jquast
jquast deleted the jq/libwcwidth-rc branch September 15, 2026 21:45
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