Changes for version 0.007 - 2026-02-10

  • New: code ref (callback) map entries for dynamic replacement in replace() — callback receives the character, return value becomes the replacement — return undef to keep original, empty string to delete — replace_inplace() croaks on code ref entries (use replace() instead)
  • Fix: memory leak when a code ref callback dies during replace() (reply SV was not freed on exception; now uses G_EVAL + croak_sv)
  • Fix taint propagation: replace() and trim() now correctly propagate the taint flag from input to output (previously laundered tainted data)
  • New trim_inplace(): zero-allocation in-place whitespace trimming (modifies string directly, returns count of bytes removed)
  • UTF-8 safety: multi-byte sequences (>= 0x80) are now copied through unchanged; replacement map is only applied to ASCII bytes (0x00-0x7F)
  • IV/NV map entries: integer values treated as character ordinals (chr)
  • Empty string map entries now delete the character from output
  • Fix off-by-one: map[255] is now reachable (>= vs > boundary)
  • Fix type safety: unsigned char for byte handling, STRLEN for loop vars
  • New replace_inplace(): zero-allocation in-place 1:1 byte replacement (up to 3.5x faster than replace() for long strings)
  • New build_map(): convenience constructor from char => replacement pairs
  • Perf: replace() writes directly into SV buffer (avoids temp alloc+copy)
  • Perf: precomputed 256-byte lookup table fast path for 1:1 maps in both replace() and replace_inplace() — eliminates per-byte SV type dispatch; replace() on long strings is now faster than Perl's tr///
  • Refactor: extract UTF8_SEQ_LEN macro for shared UTF-8 byte handling

Modules

Perl naive XS character replacement as an alternate to substitute or transliterate