Skip to content

Convert argv through the engine's own UTF-8 converter#29

Merged
xroche merged 1 commit into
masterfrom
cleanup/share-engine-utf8-converter
Jul 15, 2026
Merged

Convert argv through the engine's own UTF-8 converter#29
xroche merged 1 commit into
masterfrom
cleanup/share-engine-utf8-converter

Conversation

@xroche

@xroche xroche commented Jul 15, 2026

Copy link
Copy Markdown
Owner

What

Replace the GUI's private strdupt_utf8() — 30 lines of hand-rolled CP_ACP -> wide -> CP_UTF8 — with a thin wrapper that delegates to the engine's own converter, hts_convertStringSystemToUTF8().

Why

PR #28 added strdupt_utf8() so the GUI hands the engine UTF-8 argv (MFC gives us the ANSI codepage; the engine reads every char* as UTF-8). The engine has always done the identical conversion for its own command line, and it now exports that converter as HTSEXT_API (engine #582). Two copies of the same MBCS→UTF-8 logic is exactly the duplication that export was meant to remove.

How

The wrapper stays (so the argv call site and the --selftest are untouched); only its body changes. Verified equivalent before swapping:

  • Codepage — the engine converter uses GetACP(), precisely the CP_ACP the GUI passed. Same bytes in, same bytes out.
  • Lifetimemalloct/freet/strdupt are thin aliases over libc malloc/free (htssafe.h), and the conversion path returns plain malloc'd memory. Under /MD everything shares the one ucrtbase heap, so an argv[] entry stays freet()-able across the DLL boundary.
  • Contract — the engine returns NULL on failure; strdupt_utf8() must not, since argv[] entries have to be non-NULL. The wrapper keeps the strdupt(s) fallback.

hts_convertStringSystemToUTF8 is declared locally with extern "C" (the GUI's pattern for engine functions) rather than by including htscharset.h, which has no extern "C" guard.

CI still asserts MBCS->UTF-8 ok via --selftest.

🤖 Generated with Claude Code

PR #28 gave the GUI a private strdupt_utf8() that hand-rolls CP_ACP -> wide ->
CP_UTF8 to hand the engine UTF-8 argv. The engine has always done the same thing
for its own command line; it now exports that converter as HTSEXT_API
(hts_convertStringSystemToUTF8, engine #582), so keep one implementation, not two.

Verified equivalent before swapping:
- Codepage: the engine converter uses GetACP(), which is exactly the CP_ACP the GUI
  passed. Same bytes in, same bytes out.
- Lifetime: malloct/freet/strdupt are thin aliases over libc malloc/free (htssafe.h),
  and the conversion path returns plain malloc'd memory. Under /MD everything shares
  the one ucrtbase heap, so an argv[] entry stays freet()-able across the DLL boundary.
- Contract: the engine returns NULL on failure; strdupt_utf8() must not, since argv[]
  entries have to be non-NULL. The wrapper keeps the strdupt(s) fallback.

The wrapper stays, so the argv call site and the --selftest are unchanged; CI still
asserts "MBCS->UTF-8 ok".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@xroche
xroche merged commit cab147d into master Jul 15, 2026
3 checks passed
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.

1 participant