Can Lua support case-insensitive method calls?

2.3k views Asked by At

I'm using Lua as a data description language for my C++ app. I have a bunch of C++ classes bound to Lua using SLB 2.0. I have methods bound such as 'SetPos' or 'SetName'. I specify the position or name (for example) using a table with values keyed as 'pos' or 'name'. I want to be able to take the key, prepend 'set', and call the method, if it exists (it may not). Is that possible? If so, any suggestions?

I know I could make my bound methods lower case, but I'd rather keep them the same as the methods they're bound to (that may be my fallback though). I could try to build the method name based on my naming standards, but case insensitivity is less error prone.

I feel there should be a tricky piece of Lua that could solve this using metatables, but I haven't been able to work it out myself.

Any suggestions?

Thanks!

1

There are 1 answers

2
Nicol Bolas On BEST ANSWER

Case insensitivity is not really something Lua handles. All table lookups and local variable accesses are ultimately case sensitive string compares.

The best solution would be to just accept that you're dealing with a case sensitive system, just like C++, and deal with it.

However, if you really want to, you can do this. The simplest way would be to put every possible case permutation of a name in your function table. So your function table would have this:

["setname"] = theFunction,
["Setname"] = theFunction,
["sEtname"] = theFunction,
["SEtname"] = theFunction,
...

You can of course automate this with a function that takes each name in the table and replicates its data based on the case permutations.

A more involved but easier to use mechanism would be to use the __index and __newindex metamethods along with the empty table trick.

function CreateCaseInsensitiveTable()
  local metatbl = {}

  function metatbl.__index(table, key)
    if(type(key) == "string") then
      key = key:lower()
    end

    return rawget(table, key)
  end

  function metatbl.__newindex(table, key, value)
    if(type(key) == "string") then
      key = key:lower()
    end

    rawset(table, key, value)
  end

  local ret = {}
  setmetatable(ret, metatbl)
  return ret
end

Instead of creating a table with {}, you create the table with this function call. The table should otherwise function as normal (though obviously member access will be slightly slower).