|  | 
          1楼
          巨大八爪鱼
          2016-6-7 14:50
          
          
            #pragma once
 #define PL_FREENAME 2
 #define PL_FREEVALUE 1
 
 typedef struct _tagParam
 {
 LPWSTR lpszName;
 LPWSTR lpszValue;
 UINT uFree;
 struct _tagParam *pNext;
 } PARAMW, *LPPARAMW;
 
 #ifdef _PARAMLIST_EXPORT
 class _declspec(dllexport) ParamListW
 #else
 class ParamListW
 #endif
 {
 public:
 ParamListW(void);
 ParamListW(LPCWSTR lpSource);
 ParamListW(const ParamListW &pl);
 ~ParamListW(void);
 
 ParamListW &operator = (const ParamListW &pl);
 friend ParamListW operator + (const LPWSTR &a, const ParamListW &pl);
 ParamListW operator + (const ParamListW &pl);
 ParamListW &operator += (const ParamListW &pl);
 
 static void CopyParam(LPPARAMW lpDest, LPPARAMW lpSource);
 static void CopyParam(LPPARAMW lpSource, LPWSTR *ppName, LPWSTR *ppValue);
 static void FreeParam(LPPARAMW lpParam);
 
 UINT Combine(const ParamListW &pl, bool bMerge = true);
 void CopyParam(LPPARAMW lpSource);
 UINT Count(void) const;
 LPWSTR GetResult(void) const;
 bool HasParam(LPCWSTR szName, LPPARAMW *ppParam = NULL) const;
 bool IsEmpty(void) const;
 void RemoveAll(void);
 bool RemoveParam(LPCWSTR szName);
 void SetParam(LPWSTR szName, int nValue);
 void SetParam(LPWSTR szName, LPWSTR szValue, UINT uFree = NULL);
 void SetParam(LPWSTR szName, WCHAR ch);
 void SetResult(LPCWSTR lpSource);
 
 protected:
 LPPARAMW pParams;
 LPPARAMW pRear;
 };
 
 //#ifdef _UNICODE
 typedef ParamListW ParamList;
 /*#else
 typedef ParamListA ParamList;
 #endif*/
 
 
 | 
    
      |  | 
          2楼
          巨大八爪鱼
          2016-6-7 14:52
          
          
            ParamListW operator + (const LPWSTR &a, const ParamListW &pl){
 ParamListW obj(a);
 obj.Combine(pl);
 return obj;
 }
 在头文件外实现函数时,不能加上类名“ParamListW::”
 这是个友元普通函数,而非成员函数
 
 | 
    
      |  | 
          3楼
          巨大八爪鱼
          2016-6-7 14:55
          
          
            当重载“基本类型 + 类对象”时,需要定义一个名为operator+的普通函数,并在类中声明为友元,参数个数为两个。只有重载”类对象 + 基本类型”时,才在类中定义“operator+”成员函数,参数个数为一个。
 函数的返回值为加法运算的结果。
 参数必须是const修饰。
 而且此时const LPWSTR不能写成LPCWSTR
 
 | 
    
      |  | 
          4楼
          巨大八爪鱼
          2016-6-7 14:57
          
          
            #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;
 }
 }
 
 
 | 
    
      |  | 
          5楼
          巨大八爪鱼
          2016-6-7 15:16
          
          
            ParamList类主要用到了单向链表和运算符重载(包括复制构造函数) |