Archive: Stack in plugin


Stack in plugin
  Wanted to use own plugin stack for data saving, but can't figure it out. nError=1, after pushstring_dll.

#include <windows.h>
#include <iostream.h>
#define NSIS_MAX_STRLEN 1024

typedef struct _stack_t_dll {
struct _stack_t_dll *next;
char text[NSIS_MAX_STRLEN];
} stack_t_dll;

stack_t_dll **g_stacktop;
int g_stringsize=NSIS_MAX_STRLEN;
//g_stacktop=???;

int popstring_dll(char *str);
void pushstring_dll(char *str);

void main()
{
char szResult[1024]="";
int nError;

pushstring_dll("xxx");
nError=popstring_dll(szResult);

cout << "szResult={"<< szResult <<"} ("<< nError <<")"<<endl;
}

int popstring_dll(char *str)
{
stack_t_dll *th;
if (!g_stacktop || !*g_stacktop) return 1;
th=(*g_stacktop);
lstrcpy(str,th->text);
*g_stacktop = th->next;
GlobalFree((HGLOBAL)th);
return 0;
}

void pushstring_dll(char *str)
{
stack_t_dll *th;
if (!g_stacktop) return;
th=(stack_t_dll*)GlobalAlloc(GPTR,sizeof(stack_t_dll)+g_stringsize);
lstrcpyn(th->text,str,g_stringsize);
th->next=*g_stacktop;
*g_stacktop=th;
}

Well... normally you can do that in pure C++

#include <iostream>


>class Stack
>{
public:
Stack();
~
Stack();
void Push(const std::string&);
int Pop(std::string&);
private:
std::string s;
};

>Stack::Stack()
{
s = "";
}
>Stack::~Stack()
{
s = "";
}
>void Stack::Push(const std::string& str)
{
s = str;
}
>int Stack::Pop(std::string& buff)
{
if (s.empty()) return 0;
buff = s;
s = "";
return1;
}

>int main()
{
using namespace std;
Stack stack;
string buff1, buff2;
int nError = 0;
stack.Push("nsis");
nError = stack.Pop(buff1);
//0 = empty
//1 = not empty
cout << "Code: " << nError << "\nStack: " << buff1.c_str() << endl;
nError = stack.Pop(buff2);
cout << "Code: " << nError << "\nStack: " << buff2.c_str() << endl;
stack.Push("nsis2.08");
nError = stack.Pop(buff2);
cout << "Code: " << nError << "\nStack: " << buff2.c_str() << endl;

// wait until a keypress to exit
cin.get();
return0;
}

Thank you Joel! Work great, but I still wanted to find "C" solution (point of principle :) )


At last:


#include <windows.h>
#include <iostream.h>

#define NSIS_MAX_STRLEN 1024

typedef struct _stack_dll {
struct _stack_dll *next;
char string[NSIS_MAX_STRLEN];
} stack_dll;

stack_dll *pStackTop;

int popstring_dll(char *str);
void pushstring_dll(char *str);

void main()
{
char szResult1[1024]="";
char szResult2[1024]="";
int nError1;
int nError2;

pushstring_dll("xxx");
pushstring_dll("YYY");
nError1=popstring_dll(szResult1);
nError2=popstring_dll(szResult2);

cout << "szResult={"<< szResult1 <<"} ("<< nError1 <<")"<<endl;
cout << "szResult={"<< szResult2 <<"} ("<< nError2 <<")"<<endl;
}

void pushstring_dll(char *str)
{
stack_dll *pStackNew;
pStackNew=(stack_dll*)GlobalAlloc(GPTR, sizeof(stack_dll));
lstrcpyn(pStackNew->string, str, NSIS_MAX_STRLEN);
pStackNew->next=pStackTop;
pStackTop=pStackNew;
}

int popstring_dll(char *str) //0 on success, 1 on empty stack
{
stack_dll *pStackTemp;
if (!pStackTop) return 1;
pStackTemp=pStackTop;
lstrcpy(str, pStackTemp->string);
pStackTop=pStackTemp->next;
GlobalFree((HGLOBAL)pStackTemp);
return 0;
}

I found it interesting to playing with chain of structures.

Standart NSIS stack functions: push_front, pop_front;
Other stack functions: push_back, stack_read, stack_size.


#include <windows.h>
#include <iostream.h>

#define NSIS_MAX_STRLEN 1024

typedef struct _stack_dll {
struct _stack_dll *next;
char string[NSIS_MAX_STRLEN];
} stack_dll;

stack_dll *pStackFirst;
stack_dll *pStackTop;

void push_back(char *str);
void push_front(char *str);
int pop_front(char *str);
int stack_read(char *str, int index);
int stack_size();

void main()
{
char szRes1[1024],szRes2[1024],szRes3[1024],szRes4[1024],szRes5[1024]="";
char szRead[1024]="";
int nEr1,nEr2,nEr3,nEr4,nEr5;
int nErRead;
int nSize;

push_back("1a");
push_back("2a");
push_back("3a");
push_front("4a");

nErRead=stack_read(szRead, 2);

nSize=stack_size();

nEr1=pop_front(szRes1);
nEr2=pop_front(szRes2);
nEr3=pop_front(szRes3);
nEr4=pop_front(szRes4);
nEr5=pop_front(szRes5);

cout << "szRes1={"<< szRes1 <<"} ("<< nEr1 <<")"<<endl;
cout << "szRes2={"<< szRes2 <<"} ("<< nEr2 <<")"<<endl;
cout << "szRes3={"<< szRes3 <<"} ("<< nEr3 <<")"<<endl;
cout << "szRes4={"<< szRes4 <<"} ("<< nEr4 <<")"<<endl;
cout << "szRes5={"<< szRes5 <<"} ("<< nEr5 <<")"<<endl;
cout << "szRead={"<< szRead <<"} ("<< nErRead <<")"<<endl;
cout << "nSize={"<< nSize <<"}"<<endl;
}

//Adds an element to the beginning of the stack.
void push_back(char *str)
{
stack_dll *pStackNew;
pStackNew=(stack_dll*)GlobalAlloc(GPTR, sizeof(stack_dll));
lstrcpyn(pStackNew->string, str, NSIS_MAX_STRLEN);
if (pStackFirst) pStackFirst->next=pStackNew;
if (!pStackFirst) pStackTop=pStackNew;
pStackFirst=pStackNew;
}

//Adds an element to the top of the stack.
void push_front(char *str)
{
stack_dll *pStackNew;
pStackNew=(stack_dll*)GlobalAlloc(GPTR, sizeof(stack_dll));
lstrcpyn(pStackNew->string, str, NSIS_MAX_STRLEN);
pStackNew->next=pStackTop;
pStackTop=pStackNew;
if (!pStackFirst) pStackFirst=pStackNew;
}

//Removes the element from the top of the stack and puts it in the buffer.
//Returns: 0 on success, 1 on empty stack
int pop_front(char *str)
{
stack_dll *pStackTemp;
if (!pStackTop) return 1;
pStackTemp=pStackTop;
lstrcpy(str, pStackTemp->string);
pStackTop=pStackTemp->next;
GlobalFree((HGLOBAL)pStackTemp);
return 0;
}

//Finds the element with index and puts it in the buffer.
//Returns: 0 on success, 1 on empty stack
int stack_read(char *str, int index)
{
stack_dll *pStackTemp=pStackTop;
int sum;

for (sum=1; (pStackTemp); ++sum)
{
if (sum == index)
{
lstrcpy(str, pStackTemp->string);
return 0;
}
pStackTemp=pStackTemp->next;
}
return 1;
}

//Returns: the number of elements in the stack.
int stack_size()
{
stack_dll *pStackTemp=pStackTop;
int sum;

for (sum=0; (pStackTemp); ++sum)
pStackTemp=pStackTemp->next;
return sum;
}

STL and vectors are easier, but as you said you want C style -_-