BSL:String comparison

From OniGalore
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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:

  1. A test subject (the "A_t48" AI character) and its slightly modified death function "t48_dead(string ai_name)".
  2. A global BSL string variable "BOB_string".
  3. A lot of wasted time while searching for all those damned addresses ^_^.

The test was set as follows:

  1. 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".
  2. There is a BSL function "t48_dead(string ai_name)". This function is called by the engine when the AI character "A_t48" dies.
  3. Inside the function t48_dead(), there is an immediate comparison of "ai_name" and "BOB_string".
  4. 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.

  1. Data regarding global variable "BOB_string".
    BSL-strcmp-01 gbStrVar-Ptr.png BSL-strcmp-02 gbStrVar-PointedMemory.png
  2. Data regarding local variable "ai_name" (relevant only during the execution of the t48_dead() function).
    BSL-strcmp-03 ainame-Ptr.png BSL-strcmp-04 ainame-PointedMemory.png
  3. State of memory at the moment when the string comparison was evaluated the first time (as 'false') and the second time (as 'true').
    BSL-strcmp-05 comparison-false.png BSL-strcmp 06 comparison-true.png

Conclusion

  1. 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).
  2. When keeping track of a BSL string, Oni thus uses a pointer to the given C string.
  3. 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).
  4. 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.
  5. 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.