1
/* (c) Gustav Hartvigsson 2020
5
0) You is granted to copy, redistrubute, modify, redistrubute
6
modified copies of the software, in any shape or form.
7
1) You are not obligated to give credit the original author(s) of
8
the sofware, but it would be cool of you if you did.
9
2) You are allowed to removed the copyright notice if you want to,
10
it is up to you, but it would be cool if you did not.
15
private static GLib.Tree<string, Type?> list_of_types;
17
private static GLib.Tree<FieldInfo?, uint16> mask_cache;
20
list_of_types = new GLib.Tree<string, Type?> ((a, b) => {
21
return (GLib.strcmp (a,b));
24
mask_cache = new GLib.Tree<FieldInfo?, uint16> ((a, b) => {
29
public void deinit () {
30
list_of_types.foreach ((_key, _val) => {
31
list_of_types.remove (_key);
37
public static bool add_type_v (string name, FieldInfo first_field, ...) {
40
GLib.List<FieldInfo?> lst = new GLib.List<FieldInfo?> ();
42
lst.append (first_field);
43
for (FieldInfo? fi = va.arg<FieldInfo> (); fi != null;
44
fi = va.arg<FieldInfo> ()) {
48
FieldInfo[] lst2 = new FieldInfo[lst.length ()];
50
for (uint i = 0; i < lst.length (); i++) {
51
lst2[i] = lst.nth_data (i);
54
return add_type (name, lst2);
58
* @Return true on error.
60
public bool add_type (string name, FieldInfo[] fields) {
61
GLib.List<FieldInfo?> lst = new GLib.List<FieldInfo?> ();
63
foreach (FieldInfo fi in fields) {
67
if (lst.length () >= 16) {
71
lst.sort ((a,b) => {return a.compare (b);});
74
for (uint8 i = 0; i < lst.length (); i++) {
75
var a = lst.nth_data (i);
76
// We valitade the items whilst we are at it.
78
GLib.critical ("Validtion of FieldInfo object failed: (%s)",
82
for (uint8 j = i + 1; i < lst.length (); j++) {
83
var b = lst.nth_data (j);
88
GLib.critical ("Overlappinng fields in \"%s\": (%s) (%s).\n" +
89
"\t Will not add bitmap type defitions.",
99
for (uint8 i = 0; i < lst.length (); i++) {
100
t.fields[i] = lst.nth_data (i);
103
list_of_types.insert (name, t);
105
// add the masks to the mask cach, so we don't have to re-calculate them
106
// each time we need them.
107
lst.foreach ((ii) => {
108
mask_cache.insert (ii, ii.generate_mask ());
115
public void set (ref uint16 data,
120
var tt = list_of_types.lookup (type_name);
122
GLib.critical ("Name \"%s\" dose not exist among the types valid types.",
126
var fi = tt.get_field_info (field_id);
127
uint16 mask = mask_cache.lookup (fi);
128
uint16 invert_mask = ~mask;
129
uint16 tmp = data & invert_mask; // everything exept the field.
132
for (uint8 i = 0; i < fi.length; i++) {
137
uint16 tmp2 = in_data & tmp_mask;
140
uint16 distance = 15 - fi.end;
143
tmp2 = tmp2 << distance;
151
public uint16 get (uint16 data,
155
var fi = list_of_types.lookup (type_name).get_field_info (field_id);
156
uint16 mask = mask_cache.lookup (fi);
157
uint16 tmp = data & mask; // only what is in the field.
160
uint16 distance = 15 - fi.end;
163
tmp = tmp >> distance;
167
Type? get_type (string name) {
168
return list_of_types.lookup (name);
172
* Create a new FieldInfo using the following syntax:
177
public struct FieldInfo {
183
public FieldInfo (int field_id, uint8 start, uint8 end, uint8 length) {
184
this.field_id = field_id;
187
this.length = length;
190
public int compare (FieldInfo other) {
191
if (this.field_id != other.field_id) {
192
return this.field_id - other.field_id;
193
} else if (this.start != other.start) {
194
return this.start - other.start;
195
} else if (this.end != other.end) {
196
return this.end - other.end;
197
} else if (this.length != other.length) {
198
return this.length - other.length;
202
if (this.start > other.start) {
204
} else if (this.start < other.start) {
207
if (this.end > other.end) {
209
} else if (this.end < other.end) {
212
if (this.length > other.length) {
214
} else if (this.length < other.length) {
224
[CCode (cname = "bit_field_field_info_compare")]
225
public static extern int static_compare (FieldInfo a, FieldInfo b);
229
public bool overlap (FieldInfo other) {
230
return (!((this.start < other.end) || (this.end > other.start)));
233
[CCode (cname = "bit_field_field_info_overlap")]
234
public static extern bool static_overlap (FieldInfo a, FieldInfo b);
237
public string to_string () {
238
return "field_id: %i start: %i, end: %i, length: %i".printf (
246
* returns true on error;
248
public bool validate () {
249
var distance = this.end - this.start + 1;
250
if (distance < 1 || distance != this.length) {
256
[CCode (cname = "bit_field_field_info_validate")]
257
public extern static bool static_validate (FieldInfo info);
259
public uint16 generate_mask () {
261
for (size_t i = 0; i < this.length; i++) {
262
mask >>= 1; // shit it over to the right one.
263
mask += 0x8000; // set the left-most bit in the field
266
// Shift over the mask to where it should start.
272
[CCode (cname = "bit_field_field_generate_mask")]
273
public extern static uint16 static_generate_mask (FieldInfo info);
280
fields = new FieldInfo[16];
281
for (uint8 i = 0; i < 16; i++) {
282
fields[i] = {255,255,255,255};
286
public string to_string () {
287
var sb = new GLib.StringBuilder ();
289
sb.append (typeof (Type).name ())
291
for (size_t i = 0; i < fields.length; i++) {
293
.append (fields[i].to_string ())
301
public FieldInfo get_field_info (int field_id) {
305
foreach (FieldInfo ij in fields) {
306
if (ij.field_id == field_id) {