tests/nsis3/share/nsis/Contrib/nsArray/nsArray.c
/*
nsArray NSIS plug-in by Stuart Welch <afrowuk@afrowsoft.co.uk>
v1.1.1.7 - 2nd December 2014
*/
#include <windows.h>
#include "nsArray.h"
#include "Array.h"
#include "pluginapi.h"
HANDLE g_hInstance;
extern struct LIST g_arrays;
// Frees memory on plug-in unload.
static UINT_PTR PluginCallback(enum NSPIM msg)
{
if (msg == NSPIM_UNLOAD)
{
UnInitArrays();
}
return 0;
}
int lstrcmpn(TCHAR* a, TCHAR* b, int m, BOOL bIgnoreCase)
{
int i, j;
for (i = 0, j = 0; j < m; i++, j++)
{
TCHAR ca = bIgnoreCase ? LOWORD(CharLower((LPTSTR)a[i])) : a[i];
TCHAR cb = bIgnoreCase ? LOWORD(CharLower((LPTSTR)b[j])) : b[j];
if (ca < cb)
return -1;
if (ca > cb)
return 1;
}
return 0;
}
// Gets the number of elements in an array.
NSISFUNC(Length)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (pArray != NULL)
{
wsprintf(pArg, TEXT("%d"), pArray->nCount);
pushstring(pArg);
bOK = TRUE;
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
// Gets a single element in an array.
NSISFUNC(Get)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (popstring(pArg) == 0 && pArray != NULL)
{
struct ELEMENT* pElement;
BOOL bDataOnly = FALSE;
if (lstrcmpn(pArg, TEXT("/at="), 4, TRUE) == 0)
{
pElement = GetElementAt(pArray, myatoi(pArg + 4));
}
else
{
pElement = GetElement(pArray, pArg);
bDataOnly = TRUE;
}
if (pElement != NULL)
{
pushstring(pElement->pData);
if (!bDataOnly)
pushstring(pElement->pKey);
bOK = TRUE;
}
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
// Adds a single value to an array.
NSISFUNC(Set)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
ALLOC_C(TCHAR, pKey, string_size);
if (pArray == NULL)
pArray = NewArray(pArg);
if (popstring(pArg) == 0)
{
if (lstrcmpn(pArg, TEXT("/at="), 4, TRUE) == 0)
{
struct ELEMENT* pElement = GetElementAt(pArray, myatoi(pArg + 4));
if (popstring(pArg) == 0 && pElement != NULL)
{
SetElementData(pElement, pArg);
bOK = TRUE;
}
}
else if (lstrcmpn(pArg, TEXT("/key="), 5, TRUE) == 0)
{
lstrcpy(pKey, pArg + 5);
if (popstring(pArg) == 0 && NewElement(pArray, pKey, pArg) != NULL)
bOK = TRUE;
}
else
{
GetNextIndex(pArray, pKey);
if (NewElement(pArray, pKey, pArg) != NULL)
bOK = TRUE;
}
}
FREE(pKey);
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
// Adds one or more values to an array.
NSISFUNC(SetList)
{
DLL_INIT();
{
int bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
ALLOC_C(TCHAR, pKey, string_size);
if (pArray == NULL)
pArray = NewArray(pArg);
bOK = TRUE;
while (popstring(pArg) == 0)
{
if (lstrcmpi(pArg, TEXT("/end")) == 0)
break;
if (lstrcmpn(pArg, TEXT("/at="), 4, TRUE) == 0)
{
struct ELEMENT* pElement = GetElementAt(pArray, myatoi(pArg + 4));
if (popstring(pArg) == 0 && pElement != NULL)
SetElementData(pElement, pArg);
else
bOK = FALSE;
}
else if (lstrcmpn(pArg, TEXT("/key="), 5, TRUE) == 0)
{
lstrcpy(pKey, pArg + 5);
if (popstring(pArg) != 0 || NewElement(pArray, pKey, pArg) == NULL)
bOK = FALSE;
}
else
{
GetNextIndex(pArray, pKey);
if (NewElement(pArray, pKey, pArg) == NULL)
bOK = FALSE;
}
}
FREE(pKey);
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
// Removes a single value from an array.
NSISFUNC(Remove)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
BOOL fList = FALSE;
struct ARRAY* pArray = GetArray(pArg);
if (popstring(pArg) == 0)
{
struct ELEMENT* pElement;
if (lstrcmpn(pArg, TEXT("/at="), 4, TRUE) == 0)
{
pElement = GetElementAt(pArray, myatoi(pArg + 4));
}
else if (lstrcmpn(pArg, TEXT("/val="), 5, TRUE) == 0)
{
pElement = GetElementByVal(pArray, pArg + 5);
}
else
{
pElement = GetElement(pArray, pArg);
}
if (pElement != NULL)
{
DeleteElement(pArray, pElement);
bOK = TRUE;
}
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
// Removes one or more values from an array.
NSISFUNC(RemoveList)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
bOK = TRUE;
while (popstring(pArg) == 0)
{
if (lstrcmpi(pArg, TEXT("/end")) == 0)
break;
if (pArray != NULL)
{
struct ELEMENT* pElement;
if (lstrcmpn(pArg, TEXT("/at="), 4, TRUE) == 0)
{
pElement = GetElementAt(pArray, myatoi(pArg + 4));
}
else if (lstrcmpn(pArg, TEXT("/val="), 5, TRUE) == 0)
{
pElement = GetElementByVal(pArray, pArg + 5);
}
else
{
pElement = GetElement(pArray, pArg);
}
if (pElement != NULL)
DeleteElement(pArray, pElement);
else
bOK = FALSE;
}
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
// Iterates through array elements.
NSISFUNC(Iterate)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
BOOL bNext = TRUE;
struct ELEMENT* pElement = NULL;
if (popstring(pArg) == 0)
{
if (lstrcmpi(pArg, TEXT("/reset")) == 0)
{
if (pArray != NULL)
{
pArray->pCurrentElement = NULL;
bOK = TRUE;
}
bNext = FALSE;
}
else if (lstrcmpi(pArg, TEXT("/prev")) == 0)
{
if (pArray != NULL)
{
pElement = GetPrevElement(pArray);
}
bNext = FALSE;
}
else
{
pushstring(pArg);
}
}
if (bNext && pArray != NULL)
{
pElement = GetNextElement(pArray);
}
if (pElement != NULL)
{
pushstring(pElement->pData);
pushstring(pElement->pKey);
bOK = TRUE;
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
#ifdef ARRAY_CLEAR
// Removes all elements from an array.
NSISFUNC(Clear)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (pArray != NULL)
{
ClearArray(pArray);
bOK = TRUE;
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
#endif
#ifdef ARRAY_SORT
// Sorts the array.
NSISFUNC(Sort)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (popstring(pArg) == 0 && pArray != NULL)
{
SortArray(pArray, (enum SA_FLAGS)myatoi_or(pArg));
bOK = TRUE;
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
#endif
#ifdef ARRAY_COPY
// Copies an array to a new array.
NSISFUNC(Copy)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (popstring(pArg) == 0 && pArray != NULL && CopyArray(pArray, pArg) != NULL)
bOK = TRUE;
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
// Copies an array's keys to a new array.
NSISFUNC(CopyKeys)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (popstring(pArg) == 0 && pArray != NULL && CopyArrayKeys(pArray, pArg) != NULL)
bOK = TRUE;
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
#endif
#ifdef ARRAY_JOIN
// Joins the elements of the array into a string.
NSISFUNC(Join)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (popstring(pArg) == 0 && pArray != NULL)
{
ALLOC_C(TCHAR, pJoined, string_size);
struct ELEMENT* pElement = pArray->pFirstElement;
int chars = 0, joinLen = lstrlen(pArg);
BOOL bNoEmpty = FALSE;
if (popstring(pJoined) == 0)
{
if (lstrcmpi(pJoined, TEXT("/noempty")) == 0)
bNoEmpty = TRUE;
else
pushstring(pJoined);
}
bOK = TRUE;
lstrcpy(pJoined, TEXT(""));
while (pElement != NULL)
{
if (*pElement->pData || !bNoEmpty)
{
int length = lstrlen(pElement->pData);
lstrcpyn(pJoined + chars, pElement->pData, string_size - chars - 1);
chars += length;
if (chars >= string_size)
{
bOK = FALSE;
break;
}
if (pElement->pNext != NULL && (*pElement->pNext->pData || !bNoEmpty))
{
lstrcpyn(pJoined + chars, pArg, string_size - chars - 1);
chars += joinLen;
}
if (chars >= string_size)
{
bOK = FALSE;
break;
}
}
pElement = pElement->pNext;
}
pushstring(pJoined);
FREE(pJoined);
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
#endif
#ifdef ARRAY_SPLIT
// Splits a string into an array using a delimiter string.
NSISFUNC(Split)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size + 1);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
ALLOC_C(TCHAR, pDel, string_size);
if (pArray == NULL)
pArray = NewArray(pArg);
if (popstring(pArg) == 0 && popstring(pDel) == 0 && pArray != NULL)
{
int i, j, nDel = lstrlen(pDel), nArg = lstrlen(pArg);
ALLOC_C(TCHAR, pKey, string_size);
ALLOC_C(TCHAR, pVal, string_size);
BOOL bNoEmpty = FALSE;
BOOL bIgnoreCase = FALSE;
while (popstring(pKey) == 0)
{
if (lstrcmpi(pKey, TEXT("/noempty")) == 0)
{
bNoEmpty = TRUE;
}
else if (lstrcmpi(pKey, TEXT("/ignorecase")) == 0)
{
bIgnoreCase = TRUE;
}
else
{
pushstring(pKey);
break;
}
}
pVal[0] = (TCHAR)NULL;
if (nArg == 0 && !bNoEmpty)
{
GetNextIndex(pArray, pKey);
NewElement(pArray, pKey, TEXT(""));
}
for (i = 0, j = 0; i <= nArg; i++)
{
if (!*pDel)
{
GetNextIndex(pArray, pKey);
pVal[0] = pArg[i];
pVal[1] = (TCHAR)NULL;
NewElement(pArray, pKey, pVal);
}
else
{
if (lstrcmpn(pArg + i, pDel, nDel, bIgnoreCase) == 0)
{
if (*pVal || !bNoEmpty)
{
GetNextIndex(pArray, pKey);
NewElement(pArray, pKey, pVal);
}
i += nDel - 1;
pVal[0] = (TCHAR)NULL;
j = 0;
}
else
{
pVal[j] = pArg[i];
pVal[j + 1] = (TCHAR)NULL;
j++;
}
}
}
if (j > 0 && (*pVal || !bNoEmpty))
{
GetNextIndex(pArray, pKey);
NewElement(pArray, pKey, pVal);
}
FREE(pKey);
FREE(pVal);
}
FREE(pDel);
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
#endif
#ifdef ARRAY_TOSTRING
// Returns a string representation of the array.
NSISFUNC(ToString)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (pArray != NULL)
{
ALLOC_C(TCHAR, pJoined, string_size);
struct ELEMENT* pElement = pArray->pFirstElement;
int chars = 0;
bOK = TRUE;
lstrcpy(pJoined, TEXT(""));
while (pElement != NULL)
{
int length = lstrlen(pElement->pKey);
lstrcpyn(pJoined + chars, pElement->pKey, string_size - chars - 1);
chars += length;
if (chars >= string_size)
{
bOK = FALSE;
break;
}
lstrcpyn(pJoined + chars, TEXT(" => "), string_size - chars - 1);
chars += 4;
if (chars >= string_size)
{
bOK = FALSE;
break;
}
length = lstrlen(pElement->pData);
lstrcpyn(pJoined + chars, pElement->pData, string_size - chars - 1);
chars += length;
if (chars >= string_size)
{
bOK = FALSE;
break;
}
if (pElement->pNext != NULL)
{
lstrcpyn(pJoined + chars, TEXT(", "), string_size - chars - 1);
chars += 2;
}
if (chars >= string_size)
{
bOK = FALSE;
break;
}
pElement = pElement->pNext;
}
pushstring(pJoined);
FREE(pJoined);
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
#endif
#ifdef ARRAY_REVERSE
// Reverses the contents of an array.
NSISFUNC(Reverse)
{
DLL_INIT();
{
BOOL bOK = FALSE;
ALLOC_C(TCHAR, pArg, string_size);
if (popstring(pArg) == 0)
{
struct ARRAY* pArray = GetArray(pArg);
if (pArray != NULL)
{
ReverseArray(pArray);
bOK = TRUE;
}
}
FREE(pArg);
if (!bOK)
extra->exec_flags->exec_error = 1;
}
}
#endif
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
g_hInstance = hInst;
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
InitArrays();
}
return TRUE;
}