00001
00002 #include "xmltk.h"
00003
00004
00005
00006 typedef struct
00007 {
00008 STRPAIR pair;
00009 DWORD dwType;
00010 }
00011 TOKENINFO, *PTOKENINFO;
00012
00013 typedef vector<TOKENINFO> VTOKENINFO;
00014
00015
00016 struct tokeninfo_cmpeq
00017 {
00018 bool operator() (const TOKENINFO &ti1, const TOKENINFO &ti2) const
00019 {
00020 return ti1.dwType == ti2.dwType &&
00021 mystrcmp(ti1.pair.first, ti2.pair.first) == 0 &&
00022 mystrcmp(ti1.pair.second, ti2.pair.second) == 0;
00023 }
00024 };
00025
00026 inline size_t myhashstr(char const *psz)
00027 {
00028 return psz ? std::hash<char const *>()(psz) : 0;
00029 }
00030
00031 struct tokeninfo_hash
00032 {
00033 size_t operator() (const TOKENINFO &ti) const
00034 {
00035 return myhashstr(ti.pair.first) +
00036 myhashstr(ti.pair.second) +
00037 ti.dwType;
00038 }
00039 };
00040
00041 typedef hash_map<TOKENINFO, unsigned int, tokeninfo_hash, tokeninfo_cmpeq> MAP_TI_INDEX;
00042
00043
00044
00045 class CTokenTable : public ITokenTable
00046 {
00047 public:
00048
00049 CL_STDMETHOD(QueryInterface) (RCLIID riid, void **ppvObj);
00050 CL_STDMETHOD_(ULONG,AddRef) ();
00051 CL_STDMETHOD_(ULONG,Release) ();
00052
00053
00054 CL_STDMETHOD_(char*, StrFromXTOKEN) (XTOKEN xt);
00055 CL_STDMETHOD_(DWORD, TypeFromXTOKEN) (XTOKEN xt);
00056 CL_STDMETHOD_(STRPAIR*, PairFromXTOKEN) (XTOKEN xt);
00057 CL_STDMETHOD_(XTOKEN, XTOKENFromStr) (char* psz, DWORD dwType);
00058 CL_STDMETHOD_(XTOKEN, XTOKENFromPair) (char *pszFirst, char *pszSecond, DWORD dwType);
00059
00060 CTokenTable() : m_cRef(1)
00061 {
00062 }
00063
00064 virtual ~CTokenTable()
00065 {
00066 for (int i = m_vtokeninfo.size() - 1; i >= 0; i--)
00067 {
00068 if (m_vtokeninfo[i].pair.first)
00069 free(m_vtokeninfo[i].pair.first);
00070 if (m_vtokeninfo[i].pair.second)
00071 free(m_vtokeninfo[i].pair.second);
00072 }
00073 }
00074
00075 private:
00076
00077 unsigned int _XTOKENToIndex(XTOKEN xt)
00078 {
00079 return xt - XT_FIRST;
00080 }
00081
00082 XTOKEN _IndexToXTOKEN(unsigned int iIndex)
00083 {
00084 return iIndex + XT_FIRST;
00085 }
00086
00087 ULONG m_cRef;
00088
00089 VTOKENINFO m_vtokeninfo;
00090 MAP_TI_INDEX m_mapti;
00091
00092 };
00093
00094
00095 bool CTokenTable::QueryInterface(RCLIID riid, void **ppvObj)
00096 {
00097 if (IsEqualCLIID(riid, &IID_IUnknownCL))
00098 {
00099 *ppvObj = (void*)static_cast<IUnknownCL*>(this);
00100 }
00101 else if (IsEqualCLIID(riid, &IID_ITokenTable))
00102 {
00103 *ppvObj = (void*)static_cast<ITokenTable*>(this);
00104 }
00105 else
00106 {
00107 return false;
00108 }
00109 AddRef();
00110 return true;
00111 }
00112
00113 ULONG CTokenTable::AddRef()
00114 {
00115 return ++m_cRef;
00116 }
00117
00118 ULONG CTokenTable::Release()
00119 {
00120 --m_cRef;
00121 if (m_cRef > 0)
00122 {
00123 return m_cRef;
00124 }
00125 delete this;
00126 return 0;
00127 }
00128
00129
00130
00131 char* CTokenTable::StrFromXTOKEN(XTOKEN xt)
00132 {
00133 UINT uIndex = _XTOKENToIndex(xt);
00134 if (uIndex >= 0 && uIndex < m_vtokeninfo.size())
00135 {
00136 return m_vtokeninfo[uIndex].pair.first;
00137 }
00138 return NULL;
00139 }
00140
00141 DWORD CTokenTable::TypeFromXTOKEN(XTOKEN xt)
00142 {
00143 UINT uIndex = _XTOKENToIndex(xt);
00144 if (uIndex >= 0 && uIndex < m_vtokeninfo.size())
00145 {
00146 return m_vtokeninfo[uIndex].dwType;
00147 }
00148 return 0;
00149 }
00150
00151 STRPAIR *CTokenTable::PairFromXTOKEN(XTOKEN xt)
00152 {
00153 UINT uIndex = _XTOKENToIndex(xt);
00154 if (uIndex >= 0 && uIndex < m_vtokeninfo.size())
00155 {
00156 return &m_vtokeninfo[uIndex].pair;
00157 }
00158 return NULL;
00159 }
00160
00161 XTOKEN CTokenTable::XTOKENFromStr(char* psz, DWORD dwType)
00162 {
00163 return XTOKENFromPair(psz, NULL, dwType);
00164 }
00165
00166 XTOKEN CTokenTable::XTOKENFromPair(char* pszFirst, char *pszSecond, DWORD dwType)
00167 {
00168 TOKENINFO ti;
00169 ti.dwType = dwType;
00170 ti.pair.first = pszFirst;
00171 ti.pair.second = pszSecond;
00172
00173 MAP_TI_INDEX::const_iterator it = m_mapti.find(ti);
00174 if (it != m_mapti.end())
00175 {
00176
00177
00178
00179 return _IndexToXTOKEN((*it).second);
00180 }
00181 else
00182 {
00183
00184
00185
00186 ti.pair.first = mystrdup(ti.pair.first);
00187 ti.pair.second = mystrdup(ti.pair.second);
00188
00189 UINT iIndex = m_vtokeninfo.size();
00190
00191 m_vtokeninfo.resize(iIndex+1);
00192 m_vtokeninfo[iIndex] = ti;
00193
00194 m_mapti.insert(MAP_TI_INDEX::value_type(ti, iIndex));
00195
00196 return _IndexToXTOKEN(iIndex);
00197 }
00198 }
00199
00200 ITokenTable *g_ptt = NULL;
00201
00202 bool GetGlobalTokenTable(RCLIID riid, void** ppv)
00203 {
00204 if (g_ptt)
00205 {
00206 return g_ptt->QueryInterface(riid, ppv);
00207 }
00208
00209 return false;
00210 }
00211
00212 void InitGlobalTokenTable()
00213 {
00214 assert (g_ptt == NULL);
00215 CTokenTable *ptt = new CTokenTable();
00216 if (ptt)
00217 {
00218 ptt->QueryInterface(&IID_ITokenTable, (void**)&g_ptt);
00219 ptt->Release();
00220 }
00221 }
00222
00223 void CleanupGlobalTokenTable()
00224 {
00225 if (g_ptt)
00226 {
00227 g_ptt->Release();
00228 g_ptt = NULL;
00229 }
00230 }