Inconsistancy in calculating string lengths when using extended characters
tracked
Mars Tamale
llStringLength delivers number of extended characters which is consistant with its Wiki docs.
llDialog limits are based on the actual number of bytes in the string which can of course be 4x that.
Recommendation: Update the Wiki to warn scripters against using UTF-8 or UTF-16 characters in llDialog messages or at least explain that its not the number of characters but the number of bytes.
Log In
Jenna Felton
Hello, I decided to post here, because the topics feels related. So, I did a test and used this script:
string TEST_LINE = "A text line (текстовая строка) #";
string sText;
integer gChannel;
integer hListen;
integer gLines;
openMenu(integer next, integer full) {
if (next) {
gLines++; sText += "\n"+TEST_LINE+(string)gLines;
}
else {
gLines = 0; sText = "";
}
string text = "";
if (full) text = "\n~~~~~~"+sText+"\n~~~~~~\n";
llOwnerSay(text+"lines: "+(string)gLines
+", chars: "
+(string)llStringLength(sText)
+", bytes: "
+(string)llStringLength(llStringToBase64(sText)));
if (sText == "") text = "«empty»";
else text = sText;
llDialog(llGetOwner(), text,
["clean", "next", "next.print"], gChannel);
}
default
{
state_entry() {
llListenRemove(hListen);
gChannel = -10000-(integer)llFrand(10000.0);
hListen = llListen(gChannel,"",llGetOwner(),"");
}
on_rez(integer start_param) { llResetScript(); }
touch_end(integer _) {
openMenu(FALSE, FALSE);
}
listen(integer chan, string name, key id, string button) {
if (button == "clean") openMenu(FALSE, FALSE);
else if (button == "next") openMenu(TRUE, FALSE);
else if (button == "next.print") openMenu(TRUE, TRUE);
}
}
It is possible to press "next" 11 times and the dialog stil opens fine:
[08:07:45] llDSL: lines: 0, chars: 0, bytes: 0
[08:07:49] llDSL: lines: 1, chars: 34, bytes: 68
[08:07:54] llDSL: lines: 2, chars: 68, bytes: 132
[08:07:56] llDSL: lines: 3, chars: 102, bytes: 196
[08:07:59] llDSL: lines: 4, chars: 136, bytes: 264
[08:08:02] llDSL: lines: 5, chars: 170, bytes: 328
[08:08:06] llDSL: lines: 6, chars: 204, bytes: 392
[08:08:08] llDSL: lines: 7, chars: 238, bytes: 460
[08:08:18] llDSL: lines: 8, chars: 272, bytes: 524
[08:08:27] llDSL: lines: 9, chars: 306, bytes: 588
[08:08:34] llDSL: lines: 10, chars: 341, bytes: 656
Pressing it again crashes the dialog function:
[08:08:40] llDSL: lines: 11, chars: 376, bytes: 724
[08:08:40] llDSL: llDialog: message too long, must be less than 512 characters
I used the "next.print" button and saved the crashing output into a text file, as UTF-8. The OS said me it is 541 Bytes, not 656. Saving as UTF-16 makes it 682 bytes.
I somehow can not get the sizez the llStringLength reports, although llStringToBase64 claims it calculates the bytes. Also llDialog seems to accept more bytes then 512.
Maestro Linden
tracked
Maestro Linden
I realized the llDialog() error message when exceeding the 512 byte limit is misleading; it states "message too long, must be less than 512 characters", but in fact it should say "bytes" instead of characters. Importing for that reason.
Mars Tamale
Also its not 512 its actually 511 according to my tests (i.e. 0 - 511 breaks it, whereas 0 - 510 doesnt)
Mars Tamale
It's true the docs (now since Jan 2024) say bytes & not characters. But I think it needs highlighting as many could misread it & consider them to be the same. Especially as most of the rest of LSL works on characters not bytes.
Also why is that a limit anyway when the reason given is so the dialog doesn't extend below the window (not that that really matters, just allow scrolling & rely on Stack?heap collision to trap it)?
Maestro Linden
needs info
Hi Mars Tamale do you have suggested language for the wiki?
It looks to me like the 2 function pages are already pretty clear about whether the limit is in bytes vs characters:
* https://wiki.secondlife.com/wiki/LlDialog indicates "message must be fewer than 512 bytes in length"
* https://wiki.secondlife.com/wiki/LlStringLength indicates "llStringLength() gets the number of characters, not bytes \ LSL-2 sees all strings as UTF-8 \ LSL-Mono sees all string as UTF-16 \ Both UTF-8 and UTF-16 use multibyte characters"
Jenna Felton
Hi Maestro Linden,
I am scripting a device with a Cyrillic menu and i stumbled over the same problem, the text has 390 characters but the llDialog printed the warning it "must be less than 512 characters".
The Wiki, indeed, tells that the string must be 512 bytes long. But the inconsistency is actually in this sentence:
If the message length is greater than or equal to 512 bytes, it shouts (again on the debug channel): "llDialog: message too long, must be less than 512 characters";
I.e. it measures the bytes but tells about characters. Can you please update the error message so that the error printed to the debug channel also calls it 'bytes'?
Also I'd prefer the llDialog would truncate the text instead not opening at all. because the menu in my case is dynamically created and it is better when at least part of the text is showing instead of the user thinks the device is dead. But I better open an other Canny for this.
Edit: Big sorry. I have no idea why i misunderstood your (second) comment, about llDialog. My replay here is needles :) not deleting all this just because of politeness :)
m
maestro20220228 Resident
Jenna Felton You're right about the llDialog script error message showing incorrect units ("characters" when it should be "bytes"). I have an internal bug report to about fixing that message.