|
|
/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
FieldTable.h
Abstract:
Field Table declarations for tracewpp.exe
field table allows tpl interpreter to work with data collected by during scanning of the source files. Author:
Gor Nishanov (gorn) 03-Apr-1999
Revision History:
Gor Nishanov (gorn) 03-Apr-1999 -- hacked together to prove that this can work
ToDo:
Clean it up
--*/
extern LPCSTR FieldNames[];
struct FieldHolder;
struct Enumerator { virtual void Reset(std::string Filter) = 0; virtual void Next(std::string Filter) = 0; virtual bool Valid() const = 0; virtual const FieldHolder* GetData() const = 0; virtual ~Enumerator(){} };
struct FieldHolder { virtual DWORD PrintField(int fieldId, FILE* f, const Enumerator **) const = 0; virtual BOOL Hidden(std::string filter="") const { return FALSE; } };
struct VectorPtrTag {}; struct VectorTag {}; struct MapTag{}; struct MapPtrTag{};
template <class T> const FieldHolder* GetFieldHolder(const T& Data, VectorPtrTag) { return Data;} template <class T> const FieldHolder* GetFieldHolder(const T& Data, VectorTag) { return &Data;} template <class T> const FieldHolder* GetFieldHolder(const T& Data, MapPtrTag) { return Data.second;} template <class T> const FieldHolder* GetFieldHolder(const T& Data, MapTag) { return &Data.second;}
template <class Container, class Tag> class EnumeratorFromContainer : public Enumerator { typedef Container::const_iterator const_iterator; const_iterator _current, _begin, _end; public:
EnumeratorFromContainer(const Container& v): _begin(v.begin()),_end(v.end()),_current(v.begin()) {} void Reset(std::string Filter) { _current = _begin; while(Valid() && GetData()->Hidden(Filter)) ++_current;} void Next(std::string Filter) { ++_current; while(Valid() && GetData()->Hidden(Filter)) ++_current; } bool Valid() const { return _current != _end; } const FieldHolder* GetData() const { return GetFieldHolder(*_current, Tag()); } };
template <class Container, class Tag> Enumerator* GetEnumFromContainer(const Container& v, Tag) { return new EnumeratorFromContainer< Container, Tag >( v ); }
#define DEFAULT_FID 0
#define TEXT_FIELD(FieldId) break; case fid_ ## FieldId: \
if (__f__ == 0) { \ printf("%s.%s can not be enumerated\n",__Object__, #FieldId); \ exit(1); \ } #define ENUM_FIELD(FieldId,FieldName,Tag) break; case fid_ ## FieldId: \
if (__pEnum__ == 0) { \ printf("%s.%s is an enumeration\n",__Object__, #FieldId); \ exit(1); \ } \ *__pEnum__ = GetEnumFromContainer(FieldName, Tag() );
#define DEFAULT_TEXT_FIELD break; case DEFAULT_FID: \
if (__f__ == 0) {printf("%s can not be enumerated\n",__Object__); exit(1);} #define DEFAULT_ENUM_FIELD(EnumName,Tag) break; case DEFAULT_FID: \
if (__pEnum__ == 0) {printf("%s is an enumeration\n",__Object__); exit(1);} \ *__pEnum__ = GetEnumFromContainer(EnumName, Tag() );
#define BEGIN_FIELD_TABLE(__ObjectName__, __Output__) \
DWORD PrintField(int __FieldId__, FILE* __Output__, const Enumerator** __pEnum__) const \ { \ DWORD __status__ = ERROR_SUCCESS; \ static char* __Object__ = #__ObjectName__; \ FILE* __f__ = __Output__; \ UNREFERENCED_PARAMETER(__pEnum__); \ switch(__FieldId__) { case -1:;
#define BEGIN_FIELD_TABLE_NONAME(__Output__) \
DWORD PrintField(int __FieldId__, FILE* __Output__, const Enumerator** __pEnum__) const \ { \ DWORD __status__ = ERROR_SUCCESS; \ FILE* __f__ = __Output__; \ UNREFERENCED_PARAMETER(__pEnum__); \ switch(__FieldId__) { case -1:;
#define END_FIELD_TABLE \
break;\ default: __status__ = ERROR_NOT_FOUND; \ ReportError("\"%s\" (%d) is not a member of \"%s\"\n",FieldNames[__FieldId__], __FieldId__,__Object__); \ exit(1); \ } \ return __status__; \ }
template <class Container, class Tag> class ContainerAdapter : public FieldHolder { LPCSTR __Object__; // END_FIELD_TABLE uses __Object__ as an object name //
Container& _container; public: ContainerAdapter(LPCSTR name, Container& container): _container(container), __Object__(name) {}
BEGIN_FIELD_TABLE_NONAME(out) TEXT_FIELD(Count) fprintf(out, "%d", _container.size()); DEFAULT_ENUM_FIELD(_container, Tag) END_FIELD_TABLE };
class StringAdapter : public FieldHolder { LPCSTR __Object__; // END_FIELD_TABLE uses __Object__ as an object name //
const std::string& _string; public: StringAdapter(LPCSTR name, const std::string& string): __Object__(name), _string(string) {} BEGIN_FIELD_TABLE_NONAME(out) DEFAULT_TEXT_FIELD { fprintf(out, "%s", _string.c_str()); } END_FIELD_TABLE };
template<class Iterator> struct IteratorAdapter : FieldHolder { Iterator* theRealThing;
explicit IteratorAdapter(Iterator* aRealThing):theRealThing(aRealThing) {}
DWORD PrintField(int fieldId, FILE* f, const Enumerator** pEnum) const { return (*theRealThing)->PrintField(fieldId, f, pEnum); } };
|