|
|
/*--------------------------------------------------------------------------*
* * Microsoft Windows * Copyright (C) Microsoft Corporation, 1992 - 1999 * * File: strtable.h * * Contents: Interface file for CStringTable * * History: 25-Jun-98 jeffro Created * *--------------------------------------------------------------------------*/
#ifndef STRTABLE_H
#define STRTABLE_H
#pragma once
#include <exception> // for class exception
#include <string> // for string relational operators
#include "guidhelp.h" // for GUID relational operators
#include "stgio.h"
#include "strings.h"
#ifdef DBG
#define DECLARE_DIAGNOSITICS() \
public: void Dump() const; #else
#define DECLARE_DIAGNOSITICS() \
public: void Dump() const {} #endif
#ifdef DBG
extern CTraceTag tagStringTable; #endif // DBG
/*--------------------------------------------------------------------------
* IdentifierRange should be private to CIdentifierPool, but * compiler bugs prevent it. */ template<class T> class IdentifierRange { public: IdentifierRange(T idMin_ = T(), T idMax_ = T()) : idMin (idMin_), idMax (idMax_) { ASSERT (idMin <= idMax); }
bool operator== (const IdentifierRange<T>& other) const { return ((idMin == other.idMin) && (idMax == other.idMax)); }
bool operator!= (const IdentifierRange<T>& other) const { return (!(*this == other.idMin)); }
T idMin; T idMax; };
template<class T = int> class CIdentifierPool : public CXMLObject { public: typedef IdentifierRange<T> Range; typedef std::list<Range> RangeList;
private: #if _MSC_VER > 1300
template <class U> friend IStream& operator>> (IStream& stm, CIdentifierPool<U>& pool); template <class U> friend IStream& operator<< (IStream& stm, const CIdentifierPool<U>& pool); #else
// VC7 bug - doesn't handle template friends properly. By luck, this works.
friend IStream& operator>> (IStream& stm, CIdentifierPool<T>& pool); friend IStream& operator<< (IStream& stm, const CIdentifierPool<T>& pool); #endif
virtual void Persist(CPersistor &persistor); DEFINE_XML_TYPE(XML_TAG_IDENTIFIER_POOL);
SC ScInvertRangeList (RangeList& rlInvert) const;
#ifdef DBG
void DumpRangeList (const RangeList& l) const; #endif
public: DECLARE_DIAGNOSITICS();
CIdentifierPool (T idMin, T idMax); CIdentifierPool (IStream& stm); T Reserve(); bool Release(T idRelease); bool IsValid () const; bool IsRangeListValid (const RangeList& rl) const; SC ScGenerate (const RangeList& rlUsedIDs);
static bool AddToRangeList (RangeList& rl, const Range& rangeToAdd); static bool AddToRangeList (RangeList& rl, T idAdd);
class pool_exhausted : public exception { public: pool_exhausted(const char *_S = "pool exhausted") _THROW0() : exception(_S) {} virtual ~pool_exhausted() _THROW0() {} };
private: RangeList m_AvailableIDs; RangeList m_StaleIDs; T m_idAbsoluteMin; T m_idAbsoluteMax; T m_idNextAvailable; };
typedef CIdentifierPool<MMC_STRING_ID> CStringIDPool;
/*--------------------------------------------------------------------------
* CEntry and CStoredEntry should be private to CStringTable, * but compiler bugs prevent it. */
/*
* represents a string table entry in memory */ class CEntry : public CXMLObject { friend class CStringTable; friend class CStringEnumerator; friend struct CompareEntriesByID; friend struct CompareEntriesByString; friend struct IdentifierReleaser;
friend IStream& operator>> (IStream& stm, CEntry& entry); friend IStream& operator<< (IStream& stm, const CEntry& entry);
public: DECLARE_DIAGNOSITICS();
CEntry () : m_id(0), m_cRefs(0) {}
CEntry (const std::wstring& str, MMC_STRING_ID id) : m_str(str), m_id(id), m_cRefs(0) {} virtual LPCTSTR GetXMLType() {return XML_TAG_STRING_TABLE_STRING;} virtual void Persist(CPersistor& persistor);
private: /*
* This ctor is only used by CStringTable when reconstructing * the entry from a file. */ CEntry (const std::wstring& str, MMC_STRING_ID id, DWORD cRefs) : m_str(str) , m_id(id), m_cRefs(cRefs) {}
private: bool operator< (const LPCWSTR psz) const { return (m_str < psz); }
bool operator< (const CEntry& other) const { return (m_str < other.m_str); }
bool operator== (const LPCWSTR psz) const { return (m_str == psz); }
bool operator== (const CEntry& other) const { return (m_str == other.m_str); }
//private:
public: // temp!
std::wstring m_str; MMC_STRING_ID m_id; DWORD m_cRefs; };
struct CompareEntriesByID : public std::binary_function<const CEntry&, const CEntry&, bool> { bool operator() (const CEntry& entry1, const CEntry& entry2) const { return (entry1.m_id < entry2.m_id); } };
struct CompareEntriesByString : public std::binary_function<const CEntry&, const CEntry&, bool> { bool operator() (const CEntry& entry1, const CEntry& entry2) const { return (entry1 < entry2); } };
struct IdentifierReleaser : public std::unary_function<CEntry&, bool> { IdentifierReleaser (CStringIDPool& pool) : m_pool (pool) {}
bool operator() (CEntry& entry) const { return (m_pool.Release (entry.m_id)); }
private: CStringIDPool& m_pool; };
/*
* Because the string and ID indexes map their keys to CEntry * pointers, we must use a collection that doesn't move its * elements once they're inserted. The only STL collection * that meets this requirement is a list. */ typedef std::list<CEntry> EntryList;
typedef XMLListCollectionWrap<EntryList> CStringTable_base; class CStringTable : public CStringTable_base { friend IStream& operator>> (IStream& stm, CStringTable& entry); friend IStream& operator<< (IStream& stm, const CStringTable& entry);
public: DECLARE_DIAGNOSITICS();
CStringTable (CStringIDPool* pIDPool); CStringTable (CStringIDPool* pIDPool, IStream& stm); ~CStringTable ();
CStringTable (const CStringTable& other); CStringTable& operator= (const CStringTable& other);
/*
* IStringTable methods. Note that object doesn't implement * IStringTable, because IUnknown isn't implemented. */ STDMETHOD(AddString) (LPCOLESTR pszAdd, MMC_STRING_ID* pID); STDMETHOD(GetString) (MMC_STRING_ID id, ULONG cchBuffer, LPOLESTR lpBuffer, ULONG* pcchOut) const; STDMETHOD(GetStringLength) (MMC_STRING_ID id, ULONG* pcchString) const; STDMETHOD(DeleteString) (MMC_STRING_ID id); STDMETHOD(DeleteAllStrings) (); STDMETHOD(FindString) (LPCOLESTR pszFind, MMC_STRING_ID* pID) const; STDMETHOD(Enumerate) (IEnumString** ppEnum) const;
size_t size() const { return (m_Entries.size()); }
virtual void Persist(CPersistor& persistor) { CStringTable_base::Persist(persistor); if (persistor.IsLoading()) IndexAllEntries (); }
SC ScCollectInUseIDs (CStringIDPool::RangeList& l) const;
private:
void IndexAllEntries () { IndexEntries (m_Entries.begin(), m_Entries.end()); }
void IndexEntries (EntryList::iterator first, EntryList::iterator last) { for (; first != last; ++first) IndexEntry (first); }
void IndexEntry (EntryList::iterator);
typedef std::map<std::wstring, EntryList::iterator> StringToEntryMap; typedef std::map<MMC_STRING_ID, EntryList::iterator> IDToEntryMap;
EntryList::iterator LookupEntryByString (const std::wstring&) const; EntryList::iterator LookupEntryByID (MMC_STRING_ID) const; EntryList::iterator FindInsertionPointForEntry (const CEntry& entry) const;
#ifdef DBG
static void AssertValid (const CStringTable* pTable); #define ASSERT_VALID_(p) do { AssertValid(p); } while(0)
#else
#define ASSERT_VALID_(p) ((void) 0)
#endif
private: EntryList m_Entries; StringToEntryMap m_StringIndex; IDToEntryMap m_IDIndex; CStringIDPool* m_pIDPool; };
extern const CLSID CLSID_MMC;
/*+-------------------------------------------------------------------------*
* class CLSIDToStringTableMap * * * PURPOSE: stl::map derived class that maps snapin_clsid to stringtable * and supports XML persistence of the map collection * * NOTE: Throws exceptions! *+-------------------------------------------------------------------------*/ typedef std::map<CLSID, CStringTable> ST_base; class CLSIDToStringTableMap : public XMLMapCollection<ST_base> { public: // this method is provided as alternative to Persist, whic allows
// to cache parameter to be used to create new string tables
void PersistSelf(CStringIDPool *pIDPool, CPersistor& persistor) { m_pIDPersistPool = pIDPool; persistor.Persist(*this, NULL); } protected: // XML persistence implementation
virtual LPCTSTR GetXMLType() {return XML_TAG_STRING_TABLE_MAP;} virtual void OnNewElement(CPersistor& persistKey,CPersistor& persistVal) { CLSID key; ZeroMemory(&key,sizeof(key)); persistKey.Persist(key);
CStringTable val(m_pIDPersistPool); persistVal.Persist(val); insert(ST_base::value_type(key,val)); } private: CStringIDPool *m_pIDPersistPool; }; typedef CLSIDToStringTableMap::value_type TableMapValue;
class CMasterStringTable : public IStringTablePrivate, public CComObjectRoot, public CXMLObject { friend IStorage& operator>> (IStorage& stg, CMasterStringTable& mst); friend IStorage& operator<< (IStorage& stg, const CMasterStringTable& mst);
public: DECLARE_DIAGNOSITICS();
CMasterStringTable (); ~CMasterStringTable ();
public: DEFINE_XML_TYPE(XML_TAG_MMC_STRING_TABLE); virtual void Persist(CPersistor& persistor);
SC ScPurgeUnusedStrings();
public: /*
* ATL COM map */ BEGIN_COM_MAP (CMasterStringTable) COM_INTERFACE_ENTRY (IStringTablePrivate) END_COM_MAP ()
/*
* IStringTablePrivate methods */ STDMETHOD(AddString) (LPCOLESTR pszAdd, MMC_STRING_ID* pID, const CLSID* pclsid); STDMETHOD(GetString) (MMC_STRING_ID id, ULONG cchBuffer, LPOLESTR lpBuffer, ULONG* pcchOut, const CLSID* pclsid); STDMETHOD(GetStringLength) (MMC_STRING_ID id, ULONG* pcchString, const CLSID* pclsid); STDMETHOD(DeleteString) (MMC_STRING_ID id, const CLSID* pclsid); STDMETHOD(DeleteAllStrings) (const CLSID* pclsid); STDMETHOD(FindString) (LPCOLESTR pszFind, MMC_STRING_ID* pID, const CLSID* pclsid); STDMETHOD(Enumerate) (IEnumString** ppEnum, const CLSID* pclsid);
/*
* Shorthand into IStringTablePrivate (simulating a default parameter) */ STDMETHOD(AddString) (LPCOLESTR pszAdd, MMC_STRING_ID* pID) { return (AddString (pszAdd, pID, &CLSID_MMC)); }
STDMETHOD(GetString) (MMC_STRING_ID id, ULONG cchBuffer, LPOLESTR lpBuffer, ULONG* pcchOut) { return (GetString (id, cchBuffer, lpBuffer, pcchOut, &CLSID_MMC)); }
STDMETHOD(GetStringLength) (MMC_STRING_ID id, ULONG* pcchString) { return (GetStringLength (id, pcchString, &CLSID_MMC)); }
STDMETHOD(DeleteString) (MMC_STRING_ID id) { return (DeleteString (id, &CLSID_MMC)); }
STDMETHOD(DeleteAllStrings) () { return (DeleteAllStrings (&CLSID_MMC)); }
STDMETHOD(FindString) (LPCOLESTR pszFind, MMC_STRING_ID* pID) { return (FindString (pszFind, pID, &CLSID_MMC)); }
STDMETHOD(Enumerate) (IEnumString** ppEnum) { return (Enumerate (ppEnum, &CLSID_MMC)); }
private: CStringTable* LookupStringTableByCLSID (const CLSID* pclsid) const; SC ScGenerateIDPool ();
private: CStringIDPool m_IDPool; CLSIDToStringTableMap m_TableMap;
static const WCHAR s_pszIDPoolStream[]; static const WCHAR s_pszStringsStream[]; };
class CStringEnumerator : public IEnumString, public CComObjectRoot { public: CStringEnumerator (); ~CStringEnumerator ();
public: /*
* ATL COM map */ BEGIN_COM_MAP (CStringEnumerator) COM_INTERFACE_ENTRY (IEnumString) END_COM_MAP ()
/*
* IEnumString methods */ STDMETHOD(Next) (ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched); STDMETHOD(Skip) (ULONG celt); STDMETHOD(Reset) (); STDMETHOD(Clone) (IEnumString **ppenum);
static HRESULT CreateInstanceWrapper ( CComObject<CStringEnumerator>** ppEnumObject, IEnumString** ppEnumIface);
bool Init (const EntryList& entries);
private: typedef std::vector<std::wstring> StringVector;
StringVector m_Strings; size_t m_cStrings; size_t m_nCurrentIndex; };
IStorage& operator>> (IStorage& stg, CMasterStringTable& mst); IStorage& operator<< (IStorage& stg, const CMasterStringTable& mst); IStorage& operator>> (IStorage& stg, CComObject<CMasterStringTable>& mst); IStorage& operator<< (IStorage& stg, const CComObject<CMasterStringTable>& mst);
IStream& operator>> (IStream& stm, CStringTable& st); IStream& operator<< (IStream& stm, const CStringTable& st); IStream& operator>> (IStream& stm, CEntry& entry); IStream& operator<< (IStream& stm, const CEntry& entry);
template<class T> IStream& operator>> (IStream& stm, CIdentifierPool<T>& pool); template<class T> IStream& operator<< (IStream& stm, const CIdentifierPool<T>& pool);
#include "strtable.inl"
#endif /* STRTABLE_H */
|