Lua C++ Table Iteration - c++

I am having a slight confusion of how lua_next really works. User defines a table:
a={["a1"]=20,["a2"]=30}
I want to print this table with a C++ code:
inline int lua_print(lua_State* L)
{
wxString wxReturnStr=wxEmptyString;
wxString tempString=wxEmptyString;
int nargs = lua_gettop(L);
for (int i=1; i <= nargs; i++)
{
int type = lua_type(L, i);
switch (type)
{
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
tempString<<(lua_toboolean(L, i) ? "true" : "false");
break;
case LUA_TNUMBER:
tempString<<lua_tonumber(L, i);
break;
case LUA_TSTRING:
tempString<<lua_tostring(L, i);
break;
case LUA_TTABLE:
{
lua_pushnil(L);
while(lua_next(L,-2))
{
const char* key=lua_tostring(L,-2);
double val=lua_tonumber(L,-1);
lua_pop(L,1);
tempString<<key<<"="<<val<<"\t";
}
break;
}
default:
tempString<<lua_typename(L, type);
break;
}
wxReturnStr=wxReturnStr+tempString+"\n";
tempString=wxEmptyString;
}
lua_pop(L,nargs);
This code works very well when I call from Lua:
print(a) -- Works well
However, imagine I have a table in Lua as:
b={["b1"]=10, ["b2"]=15}
if I call the code as:
print(a,b) -- Twice prints only contents of b
My understanding with how lua_next work is in the following figure: [Edition #1]
Where is the bug?

The bug is in lua_next(L, -2) line, because -2 refers to stack top minus one, which happens here to be the last argument to print.
Use lua_next(L, i) instead.
Upd: Lua stack indexes are subject to float when moving code around at development stage, so the general advice is to pin indexes with sml int t = lua_gettop(L) just after getting/pushing/considering values and to use that t instead of -n (though this specific case appears to be sort of a keystroke bug.)

You forgot the lua_pop after processing the table.
lua_pushnil(L);
while(lua_next(L,-2))
{
const char* key=lua_tostring(L,-2);
double val=lua_tonumber(L,-1);
lua_pop(L,1);
tempString<<key<<"="<<val<<"\t";
}
lua_pop(L, 1); // THE FIX, pops the nil on the stack used to process the table
This means, that extra nil is left on the stack, so in the second iteration, the
case LUA_TNIL:
break;
just prints nothing.
About your graphics representation of the stack. The command under each image represents the state after the command was called. So the very last image is missing the [Key = a2] item on the stack.

Related

How do I avoid repetitive code in the case of switch statements which are the same but for some substituted variables/vectors/etc.?

The following snippet is from an inventory system I'm working on. I keep on running into scenarios where I fell I should be able to simple run a for loop, but am stymied by the fact that in different cases I'm using different vectors/variables/etc. I run into this problem just about any time I need to work with a variable or object who's name won't be known at run-time. In this particular situation, case 1: is exactly the same as case 2: except that the vector tankInventory[] would be dpsInventory[] in case 2:
I feel I'm doing something fundamentally backwards, but I'm not clear on how to reorient my thinking about this. Any advice?
case 1:
//loop through the inventory...
for (int i = 0; i < 6; i++)
{
//looking for an empty spot
if (tankInventory[i] == -1)
{
//add the item...
tankInventory[i] = { item };
//decrement the number of items being added
number--;
//and stop the loop if you're out of items to add
if (!number)
break;
}
}
//if there are no more items to add, break;
if (!number)
break;
//but if there are more...
else
{
//switch to main inventory...
character = 0;
//and return to the top
goto returnPoint;
}
Use a function.
Just extract the common logic out into a function, and take as parameters whatever can change.
Also, it seems like you're using goto and breaking out from the switch instead of doing a loop. I'd do something like do {} while (number) or while (number) {}, depending on what you need. This way it's much easier to use a function.
You're very likely on the right track, this is how we build up the abstractions. A simple way is to define a lambda:
// you might refine the captures
auto processInventory = [&](auto& inventoryToProcess) {
//loop through the inventory...
for (int i = 0; i < 6; i++)
{
//looking for an empty spot
if (inventoryToProcess[i] == -1)
{
//add the item...
inventoryToProcess[i] = { item };
//decrement the number of items being added
number--;
//and stop the loop if you're out of items to add
if (!number)
break;
}
}
//if there are no more items to add, break;
if (!number)
break;
//but if there are more...
else
{
//switch to main inventory...
character = 0;
//and return to the top
goto returnPoint;
}}
};
switch(condition) {
case 1:
processInventory(tankInventory);
break;
case 2:
processInventory(dpsInventory);
}

Passing a Vector<struct> to Lua table

I would like improve my code below by sending a C++ Pre-formatted Lua Table:
int GetCategory(lua_State* L)
{
uint32 Type = CHECKVAL<int>(L, 1);
lua_newtable(L);
int tbl = lua_gettop(L);
uint32 counter = 1;
// Struct CT { string CategoryBrandName, CategoryName }; > Vector<CT>
auto list = sManagerMgr->GetAll();
// Hack modify this to send a metatable/UserData/Table whatever is called
for (auto& elem : list)
{
switch (Type)
{
case 1:
lua_pushstring(L, elem->CategoryBrandName);
break;
case 2:
lua_pushstring(L, elem->CategoryName);
break;
}
lua_rawseti(L, tbl, counter);
counter++;
}
lua_settop(L, tbl);
return 1;
}
Basically,
lua_newtable pushes a table to the lua stack,
lua_gettop will take the top index, so the index where the table is at.
Then lua_pushstring(L, ELEMENT); lua_rawseti(L, tbl, counter); will put the ELEMENT to the table at the index tbl we got with gettop. The index of the element is the value of counter.
But The issue here is that i'm forced to call twice the fonction GetCategory to fill it as follow in my .lua file.
table.insert(Group, { GetCategory(1), GetCategory(2) });
Current Use :
print(i, Group(1)[i], Group(2)[i]);
So.. I would prefer to call it once and get something like this directly :
local Group =
{
[1] = { "elem->CategoryBrandName[1]", "elem->CategoryName[1]" },
[2] = { "elem->CategoryBrandName[2]", "elem->CategoryName[2]" }
--etc
};
I've tried filling elem into an 2D Array[1][2] and then pushing Array unsuccessfully
I've made a lot of research about Table, Metatables, MultiDimentional Arrays etc but I couldn't find something that would fit my need or works.
Does anyone has a solution ?
Why don't you just have your function return both values? Then you could just write
local Group = { GetCategories }
I am no expert with the C API, but I think this could be done fairly easily by just calling lua_newtable(L), so something like this:
int GetCategories(lua_State* L) {
lua_settop(L, 0);
// Discard arguments so we don't have to save the top of the stack
// and can just use numbers instead (see following lines)
lua_newtable(L); // Index 1 on stack
lua_newtable(L); // Index 2 on stack
// Do your magic
lua_settop(L, 2); // Get rid of your temp variables
return 2; // number of values we return in Lua
}
Optimization hint: you can use lua_createtable and tell it how many elements each of the tables will have so Lua can pre-allocate some memory for it.
EDIT: I just noticed this, but in your code:
for (auto& elem : list) {
switch (Type) {
case 1:
lua_pushstring(L, elem->CategoryBrandName);
break;
case 2:
lua_pushstring(L, elem->CategoryName);
break;
}
lua_rawseti(L, tbl, counter);
counter++;
}
You just keep pushing values to the stack. This may, for long vectors, overflow the stack (sooner rather than later), leading to trouble. A better approach would be to 1) push to stack 2) insert into table 3) pop them back off:
// Modified for my suggested implementation that returns
// two tables. They can easily be turned around here.
for (auto& elem : list) {
lua_pushstring(L, elem->CategoryBrandName);
lua_rawseti(L, 1, counter++);
lua_pop(L, 1);
lua_pushstring(L, elem->CategoryName);
lua_rawseti(L, 2, counter++);
lua_pop(L, 1);
}
It's always a good idea to be aware of what is and what isn't on the stack. Saving some memory can not only improve performance, but also avoid potential problems due to (Lua) stack overflow.
One last detail: You don't need ; in Lua, and it is considered bad style to use them unless you have two statements in one line print('more readable'); print('like this').
In case if anyone is looking to something similar, here's how I managed by using lua_createtable. It works as intended, It may need some improvement thought.
int GetCategory(lua_State* L)
{
int counter = 1;
int MaxListSize = 2;
auto Categories = sManagerMgr->GetAll();
lua_createtable(L, Categories.size(), 0);
for (auto& elem : Categories)
{
vector<string> list;
list.reserve(MaxListSize);
list.emplace_back(elem->CategoryBrandName);
list.emplace_back(elem->CategoryName);
Macro::Push(L, counter); // custom
lua_createtable(L, 0, MaxListSize);
for (int i = 1; i <= MaxListSize; i++)
{
Macro::Push(L, list.at(i - 1)); // custom
lua_rawseti(L, -2, i);
}
lua_settable(L, -3);
list.clear();
counter++;
}
return 1;
}
Would produce an output similar to
local Group =
{
[1] = { "elem->CategoryBrandName[1]", "elem->CategoryName[2]" },
[2] = { "elem->CategoryBrandName[1]", "elem->CategoryName[2]" }
--etc
};

Find all paths of length L in 2 D grid in C++

I'm trying to find all paths of length L in a 2-D grid(forgetting boundaries for the moment) by calling route(string s) recursively and appending to the stringth.
'l' stands for left
'r' stands for right
'd' stands for down
and
'u' stands for up
My logic is correct I think. I need to call route(string s) recursively with each of these values and append to s.
I can see the flaw in my code but cannot think of a way to correct it. I am changing the value of string s by appending to it 'r','l','u' or 'd' at each call but since successive calls are in the same scope, i get garbage answers and not the permutations of u,l,d,r that I am expecting.
#include <iostream>
#include <vector>
using namespace std;
void route(string s, int k);
int main(void){
string result="";
route("",5);
}
void route(string initial, int k){
if(initial.length()>5){
cout<<initial<<endl;
cout<<"Length of initial:"<<initial.length();
return;
}
for(int i=0;i<4;i++){
switch(i){
case 0:
{
initial.append("r");
route(initial);
}
case 1:
{
initial.append("l");
route(initial);
}
case 2:
{
initial.append("u");
route(initial);
}
case 3:
{
initial.append("d");
route(initial);
}
}
}
}
There is no need to change initial, just pass the new string to route. e.g.
route(initial + "u",k-1);
Note that you aren't using the k value currently, and you also aren't recursing for the r and l cases.
One more thing - a for loop with a switch in it for each different case, is a strange construction. Why not just call the 4 different options one after the other?
route(initial + "l",k-1);
route(initial + "r",k-1);
route(initial + "u",k-1);
route(initial + "d",k-1);

Nested redundant 'if' conditions

Is there a better (or cleaner) way to write the following code?
if(conditionX)
{
if(condition1)
{
// code X1
}
else if(condition2)
{
// code X2
}
}
else if(conditionY)
{
if(condition1)
{
// code Y1
}
else if(condition2)
{
// code Y2
}
}
I have a few more conditions, but I guess you get the point.
There are four approaches to this problem, none of which is universal:
Leave everything as is - There isn't much code duplication here. If computing condition1 and condition2 is tricky, compute them upfront and store them in bool variables
Make conditionX and conditionY produce a result that lets you unify condition1 and condition2 - This is not always possible, but in some situations you could prepare a variable that unifies the activities taken in the two branches, say, by using a function pointer or a lambda.
Put the processing logic into subclasses with virtual functions to eliminate conditional logic - This is possible only when your initial design missed an opportunity to subclass. Essentially, this approach pushes the decision on conditionX/conditionY into a place where a subclass is created, and then "reuses" that decision later on by calling a proper override of a virtual function in the interface.
Create a numeric combination representing all three conditions, and convert to switch - This trick unifies the conditionals, reducing the nesting.
Here is an example of the last approach:
int caseNumber = ((conditionX?1:0) << 3)
| ((conditionY?1:0) << 2)
| ((condition2?1:0) << 1)
| ((condition1?1:0) << 0);
switch (caseNumber) {
case 0x09:
case 0x0D:
case 0x0F: // code X1
break;
case 0x0A:
case 0x0E: // code X2
break;
case 0x05:
case 0x07: // code Y1
break;
case 0x06: // code Y2
break;
}
If your concern is with clean code in terms of viewing the source, my advice would be to segregate the blocks into their own sections, something like:
if (conditionX) processConditionX();
else if (conditionY) processConditionY();
and so on.
Then, in the sub-functions, you place the "meat":
void processConditionX (void) {
if(condition1) {
// code X1
} else if(condition2) {
// code X2
}
}
You can modify it to pass in and return parameters as necessary and I'd make the conditions and function names a little more descriptive, though I assume they're just examples here.
You can implement a state-machine instead:
#define COMBINATION(a,b,c,d) (((a)<<3)|((b)<<2)|((c)<<1)|((d)<<0))
switch (COMBINATION(conditionX,conditionY,condition1,condition2))
{
case COMBINATION(0,0,0,0): break;
case COMBINATION(0,0,0,1): break;
case COMBINATION(0,0,1,0): break;
case COMBINATION(0,0,1,1): break;
case COMBINATION(0,1,0,0): break;
case COMBINATION(0,1,0,1): CodeY2(); break;
case COMBINATION(0,1,1,0): CodeY1(); break;
case COMBINATION(0,1,1,1): CodeY1(); break;
case COMBINATION(1,0,0,0): break;
case COMBINATION(1,0,0,1): CodeX2(); break;
case COMBINATION(1,0,1,0): CodeX1(); break;
case COMBINATION(1,0,1,1): CodeX1(); break;
case COMBINATION(1,1,0,0): break;
case COMBINATION(1,1,0,1): CodeX2(); break;
case COMBINATION(1,1,1,0): CodeX1(); break;
case COMBINATION(1,1,1,1): CodeX1(); break;
}
This includes only one branch operation, so it is possibly a little more efficient (even though it also includes an additional runtime computation (at the switch line)).
As to being cleaner, I guess it's a matter of perspective, but the template above also gives you a convenient way to detect all unhandled branches within your code.
Please note that if any of the condition variables may have a value other than 1 or 0, then you should:
#define COMBINATION(a,b,c,d) (((a)?8:0)|((b)?4:0)|((c)?2:0)|((d)?1:0))
Update (attributed to #Jonathan Wakely in one of the comments below):
If you're using C++11, then you may replace the COMBINATION macro with a constexpr function:
constexpr int COMBINATION(bool a,bool b,bool c,bool d)
{
return ((int)a<<3) | ((int)b<<2) | ((int)c<<1) | ((int)d<<0);
}
I would provide the decision inside the first if as a parameter to a separated functions which then decides which code to execute, like:
if(conditionX)
{
Method1(Condition Parameters)
}
else if(conditionY)
{
Method1(Condition Parameters)
}
Another way would be to provide all needed info to a decision method (matrix), this method returns an integer which you use in a switch statement to decide which code to execute. In this way you separate the desicion logic which makes it readable and easy to unittest if needed:
DecisionMatrix(conditionX, conditionY, condition1, condition2)
{
// return a value according to the conditions for Example:
// CoditionX + Condition1 => return 1
// CoditionX + Condition2 => return 2
// CoditionY + Condition1 => return 3
// CoditionY + Condition2 => return 4
}
switch(DecisionMatrix)
{
case 1: //run code X1
break;
case 2: //run code X2
break;
case 3: //run code Y1
break;
case 4: //run code Y2
break;
}
The best way here would be to use polymorphism (Only if the chunks of code are huge)
If they are small code snippets, creating classes would obviously be an overkill.
Therefore, if there is similarity in all codes, I'd suggest a seemingly easy but really difficult task.
Try to parametrize them as much as you can.
Create a function that takes those and call them in the conditions
Now the code would be in function blocks and "cleaner"
It is always difficult to create simple things.
if (conditionX) {
method(parameterX);
else if (conditionY) {
method(parameterY);
}
where
void method(ParameterType e) {
if (condition 1) {
// Code in terms of parameter e
} else if (condition2) {
// Code in terms of parameter e
}
}
The condition that you can parametrize should be kept outside.
Hope this helps.
I think this way can be another way for solving your code.
enum ConditionParentType
{
CONDITION_NONE = 0,
CONDITION_X,
CONDITION_Y,
};
enum ConditionChildType
{
CONDITION_0 = 0,
CONDITION_1,
CONDITION_2,
};
class ConditionHandler
{
public:
explicit ConditionHandler(ConditionParentType p_type, ConditionChildType c_type)
: p_type_(p_type), c_type_(c_type) {};
void DoAction()
{
if(child_type == CONDITION_1)
{
}
else if(child_type == CONDITION_2)
{
}
else
{
//error
}
}
private:
const ConditionParentType p_type_;
const ConditionChildType c_type_;
};
int main(int argc, char *argv[])
{
ConditionParentType parent_type = GetParentType();
ConditionChildType child_type = GetChildType();
ConditionHandler handler(parent_type, child_type);
handler.DoAction();
getchar();
return 0;
}
If the combination of conditions means something then I'd write a set simple methods that return boolean values. You would end up with something like:
if (first-condition(conditionX, condition1)) {
// code X1
} else if (first-condition(conditionX, condition2)) {
// code X2
} else if (third-condition(conditionY, condition1)) {
// code Y1
} else if (fourth-condition(conditionY, condition2)) {
// code Y2
}
The names of the methods describe the conditions. Don't worry that the methods are only called once (the compiler will probably in-line them anyway), the important bit it that your code then becomes self documenting.
I'm quite surprised by the other suggested answers, which are mostly wrong if:
The two repeated conditions condition1 or condition2 are complex, in which case DRY comes into play, or
Any of the four conditions have side effects, or
Any of the conditions are slow (for example, find the minimum of a large array, or read a file), or
A boolean short-circuit is needed, as in: if (p == 0) {...} else if (p->foo == 42) {...}.
If none of these hold, as is the case 99.42% of the time, then leave the code as it is. Or, as a minor variation, change it so the nesting (that is, indentation) is only one level, not two.
Otherwise, you will need to use temporary variables as follows
const bool tstX = (conditionX);
const bool tstY = tstX || (conditionY);
const bool tst1 = tstY && (condition1);
const bool tst2 = tstY && !tst1 && (condition2);
the original code doesn't look to bad. Depending on the specific case it may or may not be more readable to do something like:
if(conditionX and condition1) {
// code X1
}
else if(conditionX and condition2) {
// code X2
}
else if(conditionY and condition1) {
// code Y1
}
else if(conditionY and condition2)
// code Y2
}

Dynamically changing size of switch-case

Following situation:
My system gets an hardware signal and writes a time value to a buffer in my
signal handler routine. Afterwards a (software) signal is sent with the time value as argument to the appropriate slot function.
The slot routine gets called correctly, but here my problem lays in:
In the slot function I have a simple switch-case statement like this:
switch(id) {
case 1:
do something..
id = 2;
break;
case 2:
start_time = val;
id = 3;
break;
case 3:
end_time = val;
id = 1;
break;
}
In those three cases I store a start and end time value between case 2 and 3 and
out of those time values I determine the elapsed time between the hardware
signals. This works fine, but now I have to measure the time sometimes "longer",
depening on parameter. This means, I can't stop the measurement at case 3 instead
I have case 4, 5, 6 and so on . What is an elegant and optimal solution for this "problem"
instead of writing:
if (param < xy) {
switch(id) {
case 1:
...
break;
case 2:
...
break;
} else if (param > xy) {
switch(id) {
case 1:
...;
break;
case 2:
...;
break;
case 3:
...;
break;
case 4:
...;
break;
case 5:
...;
break;
}
}
}
What you are describing is called a finite state machine there are a large number of excellent state machine libraries out there that will take care of the heavy lifting for you.
Take a look at this question and some of the others that it references.
You can try following:
switch ((param - xy) >= 0 ? id : -id) {
// param >= xy cases
case 1:
...
break;
case 2:
...
break;
...
// param < xy cases
case -1:
...
break;
case -2:
...
break;
...
}
Or for something fun an exciting, you could write some self modifying code to dynamically change your swithc jump table as the parameters it receives differ. You'd have to allocate a large enough area for the largest table size and play around with funciton pointers or assembler, but it could be done.
Try using a std::map of function pointers, a.k.a. jump table, rather than a switch statement. The map allows flexibility during run-time.
Store a pointer to the function, along with the case value. Search the map for the case value, retrieve the pointer and dereference to call the function.