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) => {
30
list_of_types.foreach ((_key, _val) => {
31
list_of_types.remove (_key);
37
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
add_type (name, lst2);
56
* @Return true on error.
58
public bool add_type (string name, FieldInfo[] fields) {
59
GLib.List<FieldInfo?> lst = new GLib.List<FieldInfo?> ();
61
foreach (FieldInfo fi in fields) {
65
if (lst.length () >= 16) {
69
lst.sort ((a,b) => {return a.compare (b);});
72
for (uint8 i = 0; i < lst.length (); i++) {
73
var a = lst.nth_data (i);
74
// We valitade the items whilst we are at it.
76
GLib.critical ("Validtion of FieldInfo object failed: (%s)",
80
for (uint8 j = i + 1; i < lst.length (); j++) {
81
var b = lst.nth_data (j);
86
GLib.critical ("Overlappinng fields in \"%s\": (%s) (%s).\n" +
87
"\t Will not add bitmap type defitions.",
97
for (uint8 i = 0; i < lst.length (); i++) {
98
t.fields[i] = lst.nth_data (i);
101
list_of_types.insert (name, t);
103
// add the masks to the mask cach, so we don't have to re-calculate them
104
// each time we need them.
105
lst.foreach ((ii) => {
106
mask_cache.insert (ii, ii.generate_mask ());
113
public void set (ref uint16 data,
118
var tt = list_of_types.lookup (type_name);
120
GLib.critical ("Name \"%s\" dose not exist among the types valid types.",
124
var fi = tt.get_field_info (field_id);
125
uint16 mask = mask_cache.lookup (fi);
126
uint16 invert_mask = ~mask;
127
uint16 tmp = data & invert_mask; // everything exept the field.
130
for (uint8 i = 0; i < fi.length; i++) {
135
uint16 tmp2 = in_data & tmp_mask;
138
uint16 distance = 15 - fi.end;
141
tmp2 = tmp2 << distance;
149
public uint16 get (uint16 data,
153
var fi = list_of_types.lookup (type_name).get_field_info (field_id);
154
uint16 mask = mask_cache.lookup (fi);
155
uint16 tmp = data & mask; // only what is in the field.
158
uint16 distance = 15 - fi.end;
161
tmp = tmp >> distance;
165
Type? get_type (string name) {
166
return list_of_types.lookup (name);
170
* Create a new FieldInfo using the following syntax:
175
public struct FieldInfo {
180
GLib.pointer padding;
182
public FieldInfo (int field_id, uint8 start, uint8 end, uint8 length) {
183
this.field_id = field_id;
186
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_campare (FieldInfo a, FieldInfo b);
228
public bool overlap (FieldInfo other) {
229
return (!((this.start < other.end) || (this.end > other.start)));
232
[CCode (cname = "bit_field_field_info_overlap")]
233
public static extern int static_overlap (FieldInfo a, FieldInfo b);
236
public string to_string () {
237
return "field_id: %i start: %i, end: %i, length: %i".printf (
245
* returns true on error;
247
public bool validate () {
248
var distance = this.end - this.start + 1;
249
if (distance < 1 || distance != this.length) {
255
[CCode (cname = "bit_field_field_info_validate")]
256
public extern static bool static_validate (FieldInfo info);
258
public uint16 generate_mask () {
260
for (size_t i = 0; i < this.length; i++) {
261
mask >>= 1; // shit it over to the right one.
262
mask += 0x8000; // set the left-most bit in the field
265
// Shift over the mask to where it should start.
271
[CCode (cname = "bit_field_field_generate_mask")]
272
public extern static uint16 static_generate_mask (FieldInfo info);
279
fields = new FieldInfo[16];
280
for (uint8 i = 0; i < 16; i++) {
281
fields[i] = {255,255,255,255};
285
public string to_string () {
286
var sb = new GLib.StringBuilder ();
288
sb.append (typeof (Type).name ())
290
for (size_t i = 0; i < fields.length; i++) {
292
.append (fields[i].to_string ())
300
public FieldInfo get_field_info (int field_id) {
304
foreach (FieldInfo ij in fields) {
305
if (ij.field_id == field_id) {