Skip to content

feat: Add a pluggable text codec for string patterns - #246

Open
scottanderson wants to merge 1 commit into
WerWolv:masterfrom
scottanderson:encoding
Open

feat: Add a pluggable text codec for string patterns#246
scottanderson wants to merge 1 commit into
WerWolv:masterfrom
scottanderson:encoding

Conversation

@scottanderson

@scottanderson scottanderson commented Sep 1, 2026

Copy link
Copy Markdown

Add StringEncodeDecode: an interface with decode(), encode(), and encodeLossy(). The host application sets one on the Evaluator. With none set, a string pattern keeps its raw-byte behavior.

decode() and encode() return std::optional. A nullopt result marks a byte sequence, or a character, the named encoding cannot represent. encodeLossy() never fails. It substitutes a replacement character for anything the encoding cannot represent.

PatternString routes reads and writes through the codec. getValue() and getBytesOf() throw core::err::E0004 on a nullopt result. A script can catch this error with try/catch. setValueLossy() writes through encodeLossy(), and clears the cached bytes and the cached display string; getBytesOf() otherwise reflects a write only after the next pattern run.

setValue() clears the cached bytes the same way, on every pattern type, not just PatternString.

formatDisplayValue() decodes through decode(). It returns the raw decoded text. The host application escapes the text for display.

getBytesOf() caps the encoded result to the pattern's own size. getEncodingName() reads the string's own encoding attribute.

PatternWideString keeps its fixed UTF-16 behavior. The codec does not apply to it.

Add PatternLanguage::clearFormatCaches(). It clears every placed pattern's cached display value, across every section.

Comment thread lib/include/pl/core/string_encode_decode.hpp Outdated
auto size = std::min<size_t>(this->getSize(), 0x7F);
auto *evaluator = this->getEvaluator();
const auto fullSize = this->getSize();
auto size = std::min<size_t>(fullSize, 0x7F);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this truncating still okay to do now? We should probably try to not cut codepoints in half anymore

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I attempted to improve this in the next revision

Comment thread lib/include/pl/patterns/pattern_string.hpp Outdated
Comment thread lib/include/pl/patterns/pattern_string.hpp Outdated
Add StringEncodeDecode: an interface with decode(), encode(), and
encodeLossy(). The host application sets one on the Evaluator. With
none set, a string pattern keeps its raw-byte behavior.

decode() and encode() return std::optional. A nullopt result marks a
byte sequence, or a character, the named encoding cannot represent.
encodeLossy() never fails. It substitutes a replacement character for
anything the encoding cannot represent.

PatternString routes reads and writes through the codec. getValue()
and getBytesOf() throw core::err::E0004 on a nullopt result. A script
can catch this error with try/catch. setValueLossy() writes through
encodeLossy(), and clears the cached bytes and the cached display
string; getBytesOf() otherwise reflects a write only after the next
pattern run.

setValue() clears the cached bytes the same way, on every pattern
type, not just PatternString.

formatDisplayValue() decodes through decode(), throwing the same
core::err::E0004 on a nullopt result. It reads a little past its
display budget, and backs decode() off a few bytes at a time on
failure, so a multi-byte codepoint straddling the read cutoff doesn't
report the whole value as invalid. It then trims the decoded text
itself, not the raw bytes, to the display budget, so a codepoint at
that cutoff stays whole instead of splitting mid-sequence.

getBytesOf() caps the encoded result to the pattern's own size.
getEncodingName() reads the string's own encoding attribute. With
none, it reads the evaluator's default encoding, set through
Evaluator::setDefaultEncoding().

Add a libstd #pragma encoding. It sets the evaluator's default
encoding to its value, unconditionally; the codec, not the pragma,
knows which encoding names are valid.

PatternWideString keeps its fixed UTF-16 behavior. The codec does not
apply to it.

Add PatternLanguage::clearFormatCaches(). It clears every placed
pattern's cached display value, across every section.
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