| 
              #include "stdafx.h"#include "Unicode.h"
 #define _PARAMLIST_EXPORT
 #include "ParamList.h"
 
 #define INVALID_NAME(name) ((name) == NULL || *(name) == '\0')
 
 ParamListW::ParamListW(void)
 {
 pParams = pRear = NULL;
 }
 
 ParamListW::ParamListW(LPCWSTR lpSource)
 {
 pParams = pRear = NULL;
 SetResult(lpSource);
 }
 
 ParamListW::ParamListW(const ParamListW &pl)
 {
 pParams = pRear = NULL;
 operator = (pl);
 }
 
 
 ParamListW::~ParamListW(void)
 {
 RemoveAll();
 }
 
 ParamListW &ParamListW::operator = (const ParamListW &pl)
 {
 LPPARAMW p = pl.pParams;
 LPPARAMW p2 = NULL;
 RemoveAll();
 while (p != NULL)
 {
 if (p2 == NULL)
 pParams = p2 = (LPPARAMW)malloc(sizeof(PARAMW));
 else
 {
 p2->pNext = (LPPARAMW)malloc(sizeof(PARAMW));
 p2 = p2->pNext;
 }
 CopyParam(p2, p);
 p = p->pNext;
 }
 if (p2 != NULL)
 {
 p2->pNext = NULL;
 pRear = p2;
 }
 return *this;
 }
 
 // Warning: A + B != B + A
 ParamListW operator + (const LPWSTR &a, const ParamListW &pl)
 {
 ParamListW obj(a);
 obj.Combine(pl);
 return obj;
 }
 
 ParamListW ParamListW::operator + (const ParamListW &pl)
 {
 ParamListW obj(*this);
 obj.Combine(pl);
 return obj;
 }
 
 ParamListW &ParamListW::operator += (const ParamListW &pl)
 {
 Combine(pl);
 return *this;
 }
 
 UINT ParamListW::Combine(const ParamListW &pl, bool bMerge)
 {
 UINT uCount = 0;
 LPPARAMW p;
 for (p = pl.pParams; p != NULL; p = p->pNext)
 {
 if (!bMerge && HasParam(p->lpszName))
 continue;
 
 CopyParam(p);
 uCount++;
 }
 return uCount;
 }
 
 void ParamListW::CopyParam(LPPARAMW lpDest, LPPARAMW lpSource)
 {
 CopyParam(lpSource, &lpDest->lpszName, &lpDest->lpszValue);
 lpDest->uFree = lpSource->uFree;
 }
 
 void ParamListW::CopyParam(LPPARAMW lpSource)
 {
 LPWSTR pName, pValue;
 CopyParam(lpSource, &pName, &pValue);
 SetParam(pName, pValue, lpSource->uFree);
 }
 
 void ParamListW::CopyParam(LPPARAMW lpSource, LPWSTR *ppName, LPWSTR *ppValue)
 {
 if (lpSource->uFree & PL_FREENAME)
 *ppName = DuplicateStringW(lpSource->lpszName);
 else
 *ppName = lpSource->lpszName;
 if (lpSource->uFree & PL_FREEVALUE)
 *ppValue = DuplicateStringW(lpSource->lpszValue);
 else
 *ppValue = lpSource->lpszValue;
 }
 
 UINT ParamListW::Count(void) const
 {
 UINT n = 0;
 LPPARAMW p = pParams;
 while (p != NULL)
 {
 n++;
 p = p->pNext;
 }
 return n;
 }
 
 void ParamListW::FreeParam(LPPARAMW lpParam)
 {
 if (lpParam->uFree & PL_FREENAME)
 {
 free(lpParam->lpszName);
 lpParam->lpszName = NULL;
 }
 if (lpParam->uFree & PL_FREEVALUE)
 {
 free(lpParam->lpszValue);
 lpParam->lpszValue = NULL;
 }
 }
 
 LPWSTR ParamListW::GetResult(void) const
 {
 LPPARAMW p = pParams;
 LPWSTR lpResult = NULL;
 size_t cchTotal = 0;
 bool bFirst = true;
 while (p != NULL)
 {
 LPWSTR p1 = URLEncodeW(p->lpszName);
 LPWSTR p2 = URLEncodeW(p->lpszValue);
 size_t cch1 = wcslen(p1);
 size_t cch2 = (p->lpszValue == NULL) ? 0 : wcslen(p2);
 size_t cchExtend = cch1 + cch2 + 3; // 3 more bytes for '&', '=' and '\0'
 lpResult = (LPWSTR)realloc(lpResult, (cchTotal + cchExtend) * sizeof(WCHAR));
 
 LPWCH pStr = lpResult + cchTotal;
 if (!bFirst)
 *pStr++ = L'&';
 memcpy(pStr, p1, cch1 * sizeof(WCHAR));
 pStr += cch1;
 if (p2 != NULL)
 {
 *pStr++ = L'=';
 memcpy(pStr, p2, cch2 * sizeof(WCHAR));
 pStr += cch2;
 }
 
 cchTotal = pStr - lpResult;
 free(p1);
 free(p2);
 p = p->pNext;
 bFirst = false;
 }
 if (lpResult != NULL)
 *(lpResult + cchTotal) = L'\0';
 return lpResult;
 }
 
 bool ParamListW::HasParam(LPCWSTR szName, LPPARAMW *ppParam) const
 {
 LPPARAMW p = pParams;
 while (p != NULL)
 {
 if (wcscmp(p->lpszName, szName) == 0)
 {
 if (ppParam != NULL)
 *ppParam = p;
 return true;
 }
 p = p->pNext;
 }
 if (ppParam != NULL)
 *ppParam = NULL;
 return false;
 }
 
 bool ParamListW::IsEmpty(void) const
 {
 return pParams == NULL;
 }
 
 void ParamListW::RemoveAll(void)
 {
 if (pParams == NULL)
 return;
 
 LPPARAMW p = pParams;
 LPPARAMW temp;
 while (p != NULL)
 {
 temp = p->pNext;
 FreeParam(p);
 free(p);
 p = temp;
 }
 
 pParams = pRear = NULL;
 }
 
 bool ParamListW::RemoveParam(LPCWSTR szName)
 {
 LPPARAMW p = pParams;
 LPPARAMW pPrev = NULL;
 while (p != NULL)
 {
 if (wcscmp(p->lpszName, szName) == 0)
 {
 if (pPrev != NULL)
 pPrev->pNext = p->pNext;
 else
 pParams = p->pNext; // change head
 if (p->pNext == NULL)
 pRear = pPrev; // change rear
 
 FreeParam(p);
 free(p);
 return true;
 }
 
 pPrev = p;
 p = p->pNext;
 }
 return false;
 }
 
 void ParamListW::SetParam(LPWSTR szName, int nValue)
 {
 if (INVALID_NAME(szName))
 return;
 
 LPWSTR buf = (LPWSTR)malloc(30 * sizeof(WCHAR));
 _itow_s(nValue, buf, 30, 10);
 SetParam(szName, buf, PL_FREEVALUE);
 }
 
 void ParamListW::SetParam(LPWSTR szName, LPWSTR szValue, UINT uFree)
 {
 if (INVALID_NAME(szName))
 return;
 
 LPPARAMW p;
 if (!HasParam(szName, &p))
 {
 /* Create a param at the end of pParams */
 p = (LPPARAMW)malloc(sizeof(PARAMW));
 p->pNext = NULL;
 if (pRear != NULL)
 {
 // Update pRear
 pRear->pNext = p;
 pRear = p;
 }
 else
 pParams = pRear = p; // first-created param
 }
 else
 {
 /* Change the param */
 FreeParam(p); // free old data
 }
 p->lpszName = szName; // force to use the new lpszName pointer
 p->lpszValue = szValue;
 p->uFree = uFree;
 }
 
 void ParamListW::SetParam(LPWSTR szName, WCHAR ch)
 {
 if (INVALID_NAME(szName))
 return;
 
 LPWSTR buf = (LPWSTR)malloc(2 * sizeof(WCHAR));
 buf[0] = ch;
 buf[1] = L'\0';
 SetParam(szName, buf, PL_FREEVALUE);
 }
 
 void ParamListW::SetResult(LPCWSTR lpSource)
 {
 LPWSTR lpszName = NULL;
 LPWSTR lpszValue = NULL;
 bool bFlag = false;
 RemoveAll();
 while (true)
 {
 if (*lpSource == L'?' || *lpSource == L'&' || *lpSource == L'\0')
 {
 if (bFlag)
 SetParam(lpszName, NULL, PL_FREENAME); // Pending ?param or ¶m (without value)
 if (*lpSource == L'\0')
 break;
 
 bFlag = false;
 lpSource++;
 }
 else if (*lpSource == L'=')
 {
 bFlag = true;
 lpSource++;
 }
 
 LPWSTR pPart, pDecodedPart;
 LPCWSTR pPartStart = lpSource;
 while (*lpSource != '\0' && *lpSource != '=' && *lpSource != '&')
 lpSource++;
 size_t cbPartSize = (lpSource - pPartStart) * sizeof(WCHAR);
 pPart = (LPWSTR)malloc(cbPartSize + sizeof(WCHAR));
 memcpy(pPart, pPartStart, cbPartSize);
 *(LPWCH)((LPBYTE)pPart + cbPartSize) = L'\0';
 pDecodedPart = URLDecodeW(pPart);
 free(pPart);
 
 if (!bFlag)
 lpszName = pDecodedPart;
 else
 {
 lpszValue = pDecodedPart;
 SetParam(lpszName, lpszValue, PL_FREENAME | PL_FREEVALUE);
 lpszName = lpszValue = NULL;
 }
 bFlag = !bFlag;
 }
 }
 
 
 |