-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathm_structio.h
132 lines (110 loc) · 3.77 KB
/
m_structio.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright(C) 2012 James Haley
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//-----------------------------------------------------------------------------
//
// DESCRIPTION:
// Object-oriented portable structure IO
//
//-----------------------------------------------------------------------------
#ifndef M_STRUCTIO_H__
#define M_STRUCTIO_H__
#include "m_buffer.h"
//
// Abstract base class for all structure field descriptors.
// This allows all the descriptors for a class to be iterated over in order
// even though they point to different member variable types.
//
template<typename S> class MDescriptorBase
{
protected:
MDescriptorBase<S> *next; // Next descriptor for the structure
public:
MDescriptorBase<S>(MDescriptorBase<S> *pNext) : next(pNext)
{
}
// Pure virtual. Override in each descriptor class to read that
// particular type of field out of an InBuffer and then store the
// value read into the structure instance. Return false if an IO
// error occurs.
virtual bool readField(S &structure, InBuffer &fin) = 0;
// Get the next descriptor for the structure.
MDescriptorBase<S> *nextField() const { return next; }
};
//
// Descriptor class for uint16_t structure fields.
//
template<typename S, uint16_t S::*field>
class MUint16Descriptor : public MDescriptorBase<S>
{
public:
typedef MDescriptorBase<S> Super;
MUint16Descriptor(Super *pNext) : Super(pNext) {}
// Read a uint16_t from the InBuffer and assign it to the field
// this descriptor represents.
bool readField(S &structure, InBuffer &fin)
{
return fin.readUint16(structure.*field);
}
};
//
// Descriptor class for a uint32_t structure field.
//
template<typename S, uint32_t S::*field>
class MUint32Descriptor : public MDescriptorBase<S>
{
public:
typedef MDescriptorBase<S> Super;
MUint32Descriptor(Super *pNext) : Super(pNext) {}
// Read a uint32_t from the InBuffer and assign it to the field
// this descriptor represents.
bool readField(S &structure, InBuffer &fin)
{
return fin.readUint32(structure.*field);
}
};
template<typename S> class MStructReader
{
public:
typedef MDescriptorBase<S> FieldType;
protected:
FieldType *firstField; // Descriptor for the first field in the structure.
public:
// Pass the address of the first structure field's descriptor. The remaining
// descriptors must link to each other via their constructors, in order to
// form a linked list of field descriptors.
MStructReader(FieldType *pFirstField) : firstField(pFirstField) {}
// Read all fields for this structure from an InBuffer, in the order their
// descriptors are linked together. Returns false if an IO error occurs, and
// true otherwise.
bool readFields(S &instance, InBuffer &fin)
{
FieldType *field = firstField;
// walk the descriptor list
while(field)
{
if(!field->readField(instance, fin))
return false;
field = field->nextField();
}
return true;
}
};
#endif
// EOF