Fix MString assignment operators leaving cursor at its old (stale) offset

operator=(MString)/operator=(ZString)/operator=(std::string)/operator=(const
char*)/operator=(char) all replaced the buffer's content via setSize()+
memcpy() but never reset cursor back to the start - setSize() preserves
the *offset* the cursor was already at (correct for its own use, growing
a buffer while keeping a read position stable), so a full content
replacement left the cursor sitting at whatever offset it had into the
*previous* content, not the new content. operator=(double)/operator=(int)
already did `cursor = data;` after the same setSize()+memcpy() pattern,
confirming this was the intended behavior everywhere - just missing from
the other five overloads.

This is invisible to JetCore's interpreter, which never reassigns an
already-read-from MString (each tag is a freshly parsed C++ object every
time its container is scanned, so a keyword's MString is never both read
and then reassigned on the same instance). It surfaced in a prototype JET
compiler (JetCore/jetc) built this session, which intentionally reuses
one persistent keyword slot across loop iterations instead of
reconstructing everything from text every pass - exactly the case this
bug needed. A <while expr="..."> loop reusing a slot for its condition
worked for two iterations (matching a decoy pattern: the second
assignment happened to land the stale cursor at the exact end of the
new, same-length content) and threw "operand is not valid" on the third,
since a keyword reassigned inside the loop body left the cursor already
at eod() from the read.

Verified via jstring_test/mstring_test/zstring_test/parser_test (no
regressions), JetCore's tests/posttest.sh and the two-process JSON
session persistence test (no regressions), and the jetc prototype's two
demo templates - both now produce byte-identical output to jet-2.0's
interpreter, including a <while> loop that mutates and rereads the same
keyword slot every iteration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Brad ArantandClaude Sonnet 5 committed 2026-08-23 19:18:17 -07:00
1 parent 3e6e410fe8
commit 6e4e463a96
1 file changed
+7 -2
+7 -2
View File
@@ -108,6 +108,7 @@ namespace coreutils {
setSize(value.getLength());
memcpy(data, value.getCursor(), value.getLength());
length = value.getLength();
cursor = data;
onChange();
return *this;
}
@@ -116,6 +117,7 @@ namespace coreutils {
setSize(value.getLength());
memcpy(data, value.getCursor(), value.getLength());
length = value.getLength();
cursor = data;
onChange();
return *this;
}
@@ -124,22 +126,25 @@ namespace coreutils {
setSize(value.length());
memcpy(data, value.c_str(), value.length());
length = value.length();
cursor = data;
onChange();
return *this;
}
MString &MString::operator=(const char *value) {
int len = strlen(value);
setSize(len);
memcpy(data, value, len);
cursor = data;
onChange();
return *this;
}
MString &MString::operator=(char value) {
int len = 1;
setSize(1);
*data = value;
cursor = data;
onChange();
return *this;
}