BSL:String comparison
Even though the topic is a bit complicated, the key conclusion is that BSL does not reliably support string comparison. It is strongly advised to not rely on string comparison in your BSL scripts.
Introduction
As a lot of scripters already know, BSL seemingly allows string comparison, meaning it looks like the language should be capable of processing syntax similar to the following one:
func void some_ai_died(string ai_name) { if (ai_name eq "A_t48") { dmsg("A_t48 died!"); } else { dmsg("Some other AI died!"); } }
However, string comparison appears to be a bit unreliable — sometimes it looks like it works, sometimes it does not. But why? The following research is an attempt to find the answer.
Test setup
A test was set up in the first savepoint of EnvWarehouse.
The test was composed of:
- A test subject (the "A_t48" AI character) and its slightly modified death function "t48_dead(string ai_name)".
- A global BSL string variable "BOB_string".
- A lot of wasted time while searching for all those damned addresses ^_^.
The test was set as follows:
- There is a global BSL variable "BOB_string". The init value of the variable is the string literal "A_t48". The variable can be set via various BSL functions to one of these string literals: "A_t40", "A_t41", "A_t42".
- There is a BSL function "t48_dead(string ai_name)". This function is called by the engine when the AI character "A_t48" dies.
- Inside the function t48_dead(), there is an immediate comparison of "ai_name" and "BOB_string".
- After about 5 seconds, "BOB_string" is set to be the same as "ai_name" and another comparison attempt is made.
Test results
Please see the enclosed series of figures. Figures show a relevant selection of runtime memory data.
- Data regarding global variable "BOB_string".
- Data regarding local variable "ai_name" (relevant only during the execution of the t48_dead() function).
- State of memory at the moment when the string comparison was evaluated the first time (as 'false') and the second time (as 'true').
Conclusion
- A BSL string variable seems to be stored as a C string; no additional special characters, simply a stream of bytes till the first 0x00 byte (null terminator).
- When keeping track of a BSL string, Oni thus uses a pointer to the given C string.
- If there are several independent strings which by chance contain the same text (e.g. "A_t48"), the engine still keeps separate instances of these strings (no string reuse to save memory, or any similar technique).
- When string comparison is attempted, it is most likely that the values of the pointers themselves (the memory addresses) are being compared, not the contents of the strings themselves.
- Since the engine allocates memory for local BSL variables and function arguments on demand, the address of a string such as "ai_name" will differ in each runtime session and cannot be expected at a particular position.