• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Snippet] StringIndexer

This system generates an index for any string below 8191.

JASS:
/************************************************
*
*   StringIndexer
*   v1.0.0.2
*   By Magtheridon96
*
*   - Retrieves an index for a string below 8191
*   - Helps easy string data attachment
*
*   Optional:
*   ---------
*
*       - Table by Bribe
*           - hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
*   API:
*   ----
*
*       - function IndexString takes string s returns integer
*           - Indexes a string and returns the index
*       - function GetStringId takes string s returns integer
*           - Retrieves the index of an indexed string
*       - function GetStringById takes integer id returns string
*           - Returns the string corresponding to a certain Id
*
************************************************/
library StringIndexer requires optional Table

    globals
        private string array strings
        private integer count = 0
    endglobals
    
    static if LIBRARY_Table then
        private module Init
            private static method onInit takes nothing returns nothing
                set data = Table.create()
            endmethod
        endmodule
    endif

    private struct D extends array
        static if LIBRARY_Table then
            static Table data
            
            implement Init
        else
            static hashtable data = InitHashtable()
        endif
    endstruct
    
    function GetStringById takes integer i returns string
        return strings[i]
    endfunction
    
    function GetStringId takes string t returns integer
        static if LIBRARY_Table then
            return D.data[StringHash(t)]
        else
            return LoadInteger(D.data, StringHash(t), 0)
        endif
    endfunction
    
    function IndexString takes string t returns integer
        local integer i = StringHash(t)
        
        static if LIBRARY_Table then
            if D.data[i] == 0 then
                set count = count + 1
                
                set D.data[i] = count

                set strings[count] = t
                return count
            endif

            return D.data[i]
        else
            if LoadInteger(D.data, i, 0) == 0 then
                set count = count + 1

                call SaveInteger(D.data, i, 0, count)

                set strings[count] = t
                return count
            endif

            return LoadInteger(D.data, i, 0)
        endif
    endfunction
    
endlibrary

I think it's quite nifty.

Feel free to comment.
 
Last edited:
Level 7
Joined
Dec 3, 2006
Messages
339
That is what I thought first when I saw it as well.

This might be useful for my map. For example it could be used for setting up cinematics in-game transmissions text during gameplay where I'd actually need to be using strings. Then again an in-game cinematic maker might be a bit too intense for most people.
 
Last edited:
This is more of an interface than a system.
I'm using it for Mode Manager (as soon as I make an update)

Using this would look way better than inlining the whole thing within my code.
Plus, I can totally avoid checks for mode strings that have already been registered by making the struct instance the same as the string id. (Overwriting the data would cause memory leaks (boolexprs))
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Makes me wish that Blizzard still allowed use to do the GetStringId return bug. Well you win some (hashtable) you lose some (faux code arrays, B2I, GetStringId). I suppose this thing does a job however limited the job is. It's not a requirement to be completely useful for every system in the world, it's just a requirement that it works and that it can be used for at least 1 thing, otherwise this and 90% of Nestharus resources would be pending forever.

Well it does need to have a module initializer if you are using Table and you're gonna index strings from a module. Other than that I can't see anything wrong with it.
 
Last edited:
Level 17
Joined
Apr 27, 2008
Messages
2,455
Just because you use a simple StringHash without any string formatting :

- StringHash("a/b") == StringHash("a\\b")
- StringHash("WhatEVER") == StringHash("whatever")
- maybe other stuff that i'm not aware

Well, it could be easily handled with some string formatting, but i don't think it's worth it, i just wanted to highlight it.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
That's Blizzard's fault, not mine :(

I just said how StringHash is case and "slash" insentive, nothing more, nothing less.
In fact here, i think that the insensitive case is more a pro than a con.
And for the slashs, meh who would care about it ?

What kind of string formatting are you suggesting though?

Something like that :

WhAtEver -> *wh*at*ever.

Ofc, the special characters used for the string formatting should be defined in constants.
But it will leak many strings, coz of Substring usage and string concatenations.
Futhermore, as said, i don't think it's needed anyway.
 
I don't really care about string leaks.
They're like 1 byte per character.
Using 2 different strings is theoretically slower than using 2 identical strings. (Assuming that all these strings have the same size)
This is because I'm pretty sure that a string is only hashed the first time you use it.
The second time would likely only be a check for whether it's hashed or not.

-> String leaks are not a problem.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Well, is there a practical limit size for the internal string table ?
And more strings = slower (i don't think it's O(1), right ? )

But the speed and leaks are not such an issue.
Even if i think that Nestharus did manage to create lag with huge strings leaks, and (heavy ?) strings usage.

My point is that adding this feature would be useless, more, remove a pro, but for the precision sake i had to mentionned it.
Plus, a such thing would be used for chat commands or something, right ?
Who would seriously need a case sensitivity feature ?
Again, i think about it more as a pro than a con.
 
Not only chat commands, in the future I plan to make an anti-chat spam feature ;)
It stops players from spamming the chat with an extremely fast algorithm that I have recently devised by myself :3
It's not useful for that system in particular, but it's useful for one of the plugins: Anti-cursing :D

First I'm going to have to make a poll to find the average typing speed of warcraft III players nowadays :3
 
Top