| 
            
            
             
              #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;     } }
               
                       |