forked from evilsocket/openbts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MsgBase.h
215 lines (190 loc) · 7.99 KB
/
MsgBase.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
* Copyright 2011, 2014 Range Networks, Inc.
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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.
*/
#ifndef MSGBASE_H
#define MSGBASE_H 1
#include <iostream>
#include <stdlib.h> // For size_t
#include "Defines.h"
#include "BitVector.h"
#include "ScalarTypes.h"
typedef const char *Type2Str(int);
const char *tohex(int);
// This is a package to help write downlink messages and message elements.
// (Note: A message element class is a helper class that writes part of a message,
// but is not a final class.)
// Also see Field<> and Field_z<> types.
// You write a single function writeCommon(), and this package uses it to instantiate the
// functions from MsgBase in your message class, namely:
// void writeBody(BitVector &dest, size_t &wp)
// void writeBody(BitVector &dest)
// int length()
// void text(std::ostream&os)
// To use:
// Step 1: For both message classes and message element classes:
// - Create a single function named: writeCommon(MsgCommon& dest)
// which writes out the message using the functions defined in MsgCommon,
// or the macros: WRITE_ITEM, WRITE_FIELD, etc.
// The primary output function is writeField()
// Step 2: Your message classes only (not message element classes)
// need to define the functions above. You can do this by inheriting from MsgBody,
// or just writing these yourself.
// For examples see class MsgBody or class RLCDownlinkMessage.
class MsgCommon
{
public:
size_t wp;
MsgCommon() : wp(0) {}
MsgCommon(size_t wwp) : wp(wwp) {}
// Ignore this. g++ emits the vtable and typeid in the translation unit where
// the first virtual method (meeting certain qualifications) is defined, so we use this
// dummy method to control that and put the vtables in MsgBase.cpp.
// Do not change the order of these functions here or you will get inscrutable link errors.
// What a foo bar language.
virtual void _define_vtable() {} // Must be the first function.
// The primary function to write bitfields.
virtual void writeField(
uint64_t value, // The value to be output to the BitVector by write().
unsigned len, // length in bits of value.
const char *name=0, // name to be output by text() function; if not supplied,
// then this var does not appear in the text()
Type2Str cvt=0) = 0; // optional function to translate value to a string in text().
// This is used primarily to write variables of type Field or Field_z,
// for which the width is defined in the type declaration.
virtual void writeField(const ItemWithValueAndWidth&item, const char *name = 0) = 0;
// Same as above, but an optional field whose presence is controlled by present.
virtual void writeOptFieldLH( // For fields whose presence is indicated by H, absence by L.
uint64_t value, unsigned len, int present, const char*name = 0) = 0;
// An alternative idiom to writeOptField01() is:
// if (dst.write01(present)) writeField(value,len,name);
virtual void writeOptField01( // For fields whose presence is indicated by 1, absence by 0.
uint64_t value, unsigned len, int present, const char*name = 0) = 0;
virtual void writeH() {}
virtual void writeL() {}
virtual void write0() {}
virtual void write1() {}
virtual bool write01(bool present) {return present;}
virtual void writeBitMap(bool*value,unsigned bitmaplen, const char*name) = 0;
// getStream() returns the ostream for the text() function, or NULL for
// length() or write() functions. You can use it to make your function
// do something special for text().
virtual std::ostream* getStream() { return NULL; }
};
#define WRITE_ITEM(name) writeField(name,#name)
#define WRITE_OPT_ITEM01(name,opt) writeOptField01(name,name.getWidth(),opt,#name)
#define WRITE_FIELD(name,width) writeField(name,width,#name)
#define WRITE_OPT_FIELD01(name,width,opt) writeOptField01(name,width,opt,#name)
#define WRITE_OPT_FIELDLH(name,width,opt) writeOptFieldLH(name,width,opt,#name)
class MsgCommonWrite : public MsgCommon {
BitVector& mResult;
public:
void _define_vtable();
MsgCommonWrite(BitVector& wResult) : mResult(wResult) {}
MsgCommonWrite(BitVector& wResult, size_t &wp) : MsgCommon(wp), mResult(wResult) {}
void writeField(uint64_t value, unsigned len, const char * name=0, Type2Str =0);
void writeField(const ItemWithValueAndWidth&item, const char *name = 0);
void write0() { writeField(0,1); }
void write1() { writeField(1,1); }
bool write01(bool present) { writeField(present,1); return present; }
void writeH();
void writeL();
// Write an Optional Field controlled by an initial L/H field.
void writeOptFieldLH(uint64_t value, unsigned len, int present, const char * name);
// Write an Optional Field controlled by an initial 0/1 field.
void writeOptField01(uint64_t value, unsigned len, int present, const char * name);
// Write a bitmap.
void writeBitMap(bool*value,unsigned bitmaplen, const char*name);
};
class MsgCommonLength : public MsgCommon {
public:
void _define_vtable();
void writeH() { wp++; }
void writeL() { wp++; }
void write0() { wp++; }
void write1() { wp++; }
bool write01(bool present) { wp++; return present;}
void writeField(uint64_t, unsigned len, const char* =0, Type2Str =0) { wp+=len; }
//virtual void writeField(const ItemWithValueAndWidth&item, const char *name= 0) { wp = item.getWidth(); }
virtual void writeField(const ItemWithValueAndWidth&item, const char *) { wp = item.getWidth(); }
void writeOptFieldLH(uint64_t, unsigned len, int present, const char*) {
wp++; if (present) wp += len;
}
void writeOptField01(uint64_t, unsigned len, int present, const char*) {
wp++; if (present) wp += len;
}
void writeBitMap(bool*,unsigned bitmaplen, const char*) { wp+=bitmaplen; }
};
class MsgCommonText : public MsgCommon {
std::ostream& mos;
public:
void _define_vtable();
MsgCommonText(std::ostream &os) : mos(os) { }
void writeField(const ItemWithValueAndWidth&item, const char *name = 0) {
if (name) { mos << " " << name << "=(" << item.getValue() << ")"; }
}
void writeField(uint64_t value, unsigned, const char*name=0, Type2Str cvt=0) {
if (name) {
mos << " " << name << "=";
if (cvt) { mos << cvt(value); } else { mos << value; }
}
}
void writeOptFieldLH(uint64_t value, unsigned, int present, const char*name = 0) {
if (name && present) { mos << " " << name << "=(" << value << ")"; }
}
void writeOptField01(uint64_t value, unsigned, int present, const char*name = 0) {
if (name && present) { mos << " " << name << "=(" << value << ")"; }
}
void writeBitMap(bool*value,unsigned bitmaplen, const char*name);
std::ostream* getStream() { return &mos; }
};
// This is the base class for the message, that defines the functions that use MsgCommon.
/***
class MsgBody {
public:
virtual void writeCommon(MsgCommon &dest) const = 0;
void writeOptional01(MsgCommon &dest, bool control) const {
if (control) {
dest.write1();
writeCommon(dest);
} else {
dest.write0();
}
}
void writeBody(BitVector &vdst, size_t &wwp) const {
MsgCommonWrite dest(vdst,wwp);
writeCommon(dest);
wwp = dest.wp;
}
void writeBody(BitVector &vdst) const {
MsgCommonWrite dest(vdst);
writeCommon(dest);
}
int lengthBodyBits() const {
MsgCommonLength dest;
writeCommon(dest);
return dest.wp;
}
void textBody(std::ostream&os) const {
MsgCommonText dest(os);
writeCommon(dest);
}
};
***/
/***
#define INHERIT_MSG_BASE \
void write(BitVector &dest, size_t &wp) { MsgBase::write(dest,wp); } \
void write(BitVector &dest) { MsgBase::write(dest); } \
int length() { return MsgBase::length(); } \
void text(std::ostream&os) const { MsgBase::text(os); }
***/
#endif