- Fixed a bug with the split() proc.
- Changed how the replace proc works to increase its speed by 50%.
- Added the Replace() and split() procs which are case-sensitive versions of replace and split.
- Added the prefix() and ending() procs which determine if one string starts or ends with another string. Prefix() and Ending() are the case-sensitive versions.
- Did some benchmarking to compare performance against the Deadron.TextHandling library. The benchmarking code is included as demo\benchmark.dm
Replace:
Forum_account.Text 50,000 calls in 5.700 seconds: 114 microseconds per call
Deadron.TextHandling 50,000 calls in 9.520 seconds: 190 microseconds per call
(dd_replacetext)
Split:
Forum_account.Text 50,000 calls in 3.150 seconds: 63 microseconds per call
Deadron.TextHandling 50,000 calls in 4.176 seconds: 83 microseconds per call
(dd_text2list)
Concat:
Forum_account.Text 50,000 calls in 1.894 seconds: 38 microseconds per call
Deadron.TextHandling 50,000 calls in 5.537 seconds: 110 microseconds per call
(dd_list2text)
The prefix() and ending() procs are almost identical to the dd_hasprefix and dd_hassuffix procs. Their performance is about the same and because those procs are so simple, it can't make much of a difference. The only difference is because the dd_hassuffix proc is incorrect:
dd_hassuffix(text, suffix)
var/start = length(text) - length(suffix)
if (start) return findtext(text, suffix, start)
it should be findtext(text, suffix, start + 1), otherwise this will happen:
if(dd_hassuffix("fails", "fail"))
world << "oops!"
The value of start will be length("fails") - length("fail"), which is 1. String indexes start at 1, so this is checking if the string "fail" is found in "fails" (and it is). Instead it should start checking at index = 2, so it checks if "fail" is found in "ails" (and it's not). The library even has an automatic built-in test, oops indeed!
1) The naming convention would benefit from some kind of library-specific prefix, in my opinion. The proc names you use are somewhat generic.
2) In int(), instead of using an associative list and copytext(), text2ascii() and a couple of if statements might be just as good. The only place you stand to lose is in losing the lookup from the associative list, but I doubt that's actually a problem; I think those instructions should execute pretty quickly, and you could possibly even avoid the trouble of needing to convert to uppercase. This also would let you handle bases up to 36. In addition, I would suggest the debug mode also ASSERT() that the base is an integer.
3) Based on my experience with BYOND's internals, the concat() method seems really ingenious. I'm not sure though that the cases above 10 items are really of great benefit, since the vast majority of concats will use 10 or fewer and big replacement operations will tend to be infrequent. I suspect that past 10, you'd gain a lot of simplicity and lose little in speed just by recursing into halves. If not 10, then 20 or 40 maybe. This at any rate would be a better way to handle the 321+ cases, which currently use tail recursion.