/+junk/vala-bit-field

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/%2Bjunk/vala-bit-field
3 by Gustav Hartvigsson
* It works. :-)
1
/* (c) Gustav Hartvigsson 2020
2
3
                        Cool Licence 1.0
4
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.
11
 */
12
2 by Gustav Hartvigsson
* encountered a bug in Valac:
13
namespace BitField {
14
  
15
  private static GLib.Tree<string, Type?> list_of_types;
16
  
3 by Gustav Hartvigsson
* It works. :-)
17
  private static GLib.Tree<FieldInfo?, uint16> mask_cache;
2 by Gustav Hartvigsson
* encountered a bug in Valac:
18
  
10 by Gustav Hartvigsson
* Made it able to be compiled as a library
19
  public void init () {
2 by Gustav Hartvigsson
* encountered a bug in Valac:
20
    list_of_types = new GLib.Tree<string, Type?> ((a, b) => {
21
      return (GLib.strcmp (a,b));
22
    });
23
    
3 by Gustav Hartvigsson
* It works. :-)
24
    mask_cache = new GLib.Tree<FieldInfo?, uint16> ((a, b) => {
2 by Gustav Hartvigsson
* encountered a bug in Valac:
25
       return a.compare (b);
26
    });
27
  }
28
  
10 by Gustav Hartvigsson
* Made it able to be compiled as a library
29
  public void deinit () {
2 by Gustav Hartvigsson
* encountered a bug in Valac:
30
    list_of_types.foreach ((_key, _val) => {
31
      list_of_types.remove (_key);
32
      return false;
33
    });
34
  }
35
  
10 by Gustav Hartvigsson
* Made it able to be compiled as a library
36
  public static bool add_type_v (string name, FieldInfo first_field, ...) {
2 by Gustav Hartvigsson
* encountered a bug in Valac:
37
    var va = va_list ();
38
    
39
    GLib.List<FieldInfo?> lst = new GLib.List<FieldInfo?> ();
40
    
41
    lst.append (first_field);
42
    for (FieldInfo? fi = va.arg<FieldInfo> (); fi != null;
43
                                               fi = va.arg<FieldInfo> ()) {
44
      lst.append (fi);
45
    }
46
    
3 by Gustav Hartvigsson
* It works. :-)
47
    FieldInfo[] lst2 = new FieldInfo[lst.length ()];
48
    
7 by Gustav Hartvigsson
* Woops
49
    for (uint i = 0; i < lst.length (); i++) {
50
      lst2[i] = lst.nth_data (i);
51
    }
9 by Gustav Hartvigsson
Woops
52
   
53
    return add_type (name, lst2);
3 by Gustav Hartvigsson
* It works. :-)
54
  }
55
  
56
  /**
57
   * @Return true on error.
58
   */
59
  public bool add_type (string name, FieldInfo[] fields) {
60
    GLib.List<FieldInfo?> lst = new GLib.List<FieldInfo?> ();
61
    
62
    foreach  (FieldInfo fi in fields) {
63
      lst.append (fi);
64
    }
65
    
2 by Gustav Hartvigsson
* encountered a bug in Valac:
66
    if (lst.length () >= 16) {
67
      return true;
68
    }
69
    
70
    lst.sort ((a,b) => {return a.compare (b);});
71
    
72
    
73
    for (uint8 i = 0; i < lst.length (); i++) {
74
      var a = lst.nth_data (i); 
75
      // We valitade the items whilst we are at it.
76
      if (a.validate ()) {
3 by Gustav Hartvigsson
* It works. :-)
77
        GLib.critical ("Validtion of FieldInfo object failed: (%s)",
78
                       a.to_string ());
2 by Gustav Hartvigsson
* encountered a bug in Valac:
79
        return true;
80
      }
81
      for (uint8 j = i + 1; i < lst.length (); j++) {
3 by Gustav Hartvigsson
* It works. :-)
82
        var b = lst.nth_data (j);
83
        if (b == null) {
84
          break;
85
        }
2 by Gustav Hartvigsson
* encountered a bug in Valac:
86
        if (a.overlap (b)) {
3 by Gustav Hartvigsson
* It works. :-)
87
          GLib.critical ("Overlappinng fields in \"%s\": (%s) (%s).\n" +
2 by Gustav Hartvigsson
* encountered a bug in Valac:
88
                         "\t Will not add bitmap type defitions.",
3 by Gustav Hartvigsson
* It works. :-)
89
                         name,
90
                         a.to_string (),
91
                         b.to_string ());
2 by Gustav Hartvigsson
* encountered a bug in Valac:
92
          return true;
93
        }
94
      }
95
    }
96
    
97
    Type t = Type ();
98
    for (uint8 i = 0; i < lst.length (); i++) {
99
      t.fields[i] = lst.nth_data (i);
100
    }
101
    
3 by Gustav Hartvigsson
* It works. :-)
102
    list_of_types.insert (name, t);
103
    
104
    // add the masks to the mask cach, so we don't have to re-calculate them
105
    // each time we need them.
106
    lst.foreach ((ii) => {
107
      mask_cache.insert (ii, ii.generate_mask ());
108
    });
109
    
110
    
2 by Gustav Hartvigsson
* encountered a bug in Valac:
111
    return false;
112
  }
113
  
3 by Gustav Hartvigsson
* It works. :-)
114
  public void set (ref uint16 data,
115
                   string type_name,
116
                   int field_id,
117
                   uint16 in_data) {
118
    
119
    var tt = list_of_types.lookup (type_name);
120
    if (tt == null) {
121
      GLib.critical ("Name \"%s\" dose not exist among the types valid types.",
122
                     type_name);
123
      return;
124
    }
125
    var fi = tt.get_field_info (field_id);
126
    uint16 mask = mask_cache.lookup (fi);
127
    uint16 invert_mask = ~mask;
128
    uint16 tmp = data & invert_mask; // everything exept the field.
129
    
130
    uint16 tmp_mask = 1;
131
    for (uint8 i = 0; i < fi.length; i++) {
132
      tmp_mask <<= 1;
133
      tmp_mask += 1;
134
    }
135
    
136
    uint16 tmp2 = in_data & tmp_mask;
137
    
138
    
139
    uint16 distance = 15 - fi.end;
140
    
141
    
142
    tmp2 = tmp2 << distance;
143
    
144
    
145
    tmp2 = tmp2 | tmp;
146
    
147
    data = tmp2;
148
  }
149
  
150
  public uint16 get (uint16 data,
151
                     string type_name,
152
                     int field_id) {
153
    
154
    var fi = list_of_types.lookup (type_name).get_field_info (field_id);
155
    uint16 mask = mask_cache.lookup (fi);
156
    uint16 tmp = data & mask; // only what is in the field.
157
    
158
    
159
    uint16 distance = 15 - fi.end;
160
    
161
    
162
    tmp = tmp >> distance;
163
    return tmp;
164
  }
165
  
166
  Type? get_type (string name) {
167
    return list_of_types.lookup (name);
168
  } 
169
  
170
  /**
171
   * Create a new FieldInfo using the following syntax:
172
   * {{{
13 by Gustav Hartvigsson
* removed unused code
173
   *  enum MyTypeFields {
174
   *    F1,
175
   *    F2,
176
   *    //....
177
   *  }
178
   *
179
   *  BitField.FieldInfo[] my_fields_info = {
180
   *    BitField.FieldInfo (MyTypeFields.F1, 0, 5, 6),
181
   *    BitField.FieldInfo (MyTypeFields.F2, 0, 5, 6),
182
   *    //.....
183
   *  }
184
   *  
185
   *  if (FieldInfo.add_type ("MyType", my_fields_info)) {
186
   *    stderr.printf ("Something went wrong!");
187
   *  }
3 by Gustav Hartvigsson
* It works. :-)
188
   * }}}
189
   * 
190
   */
12 by Gustav Hartvigsson
* Made the C api better.
191
  [CCode (cprefix="bit_field_info_", cname="BitFieldInfo")]
2 by Gustav Hartvigsson
* encountered a bug in Valac:
192
  public struct FieldInfo {
3 by Gustav Hartvigsson
* It works. :-)
193
    int field_id;
2 by Gustav Hartvigsson
* encountered a bug in Valac:
194
    uint8 start;
195
    uint8 end;
196
    uint8 length;
3 by Gustav Hartvigsson
* It works. :-)
197
    
198
    public FieldInfo (int field_id, uint8 start, uint8 end, uint8 length) {
199
      this.field_id = field_id;
200
      this.start = start;
201
      this.end = end;
202
      this.length = length; 
203
    }
2 by Gustav Hartvigsson
* encountered a bug in Valac:
204
    
205
    public int compare (FieldInfo other) {
206
      if (this.field_id != other.field_id) {
3 by Gustav Hartvigsson
* It works. :-)
207
        return  this.field_id - other.field_id; 
2 by Gustav Hartvigsson
* encountered a bug in Valac:
208
      } else if (this.start != other.start) {
3 by Gustav Hartvigsson
* It works. :-)
209
        return  this.start - other.start;
2 by Gustav Hartvigsson
* encountered a bug in Valac:
210
      } else if (this.end != other.end) {
3 by Gustav Hartvigsson
* It works. :-)
211
        return this.end - other.end;
2 by Gustav Hartvigsson
* encountered a bug in Valac:
212
      } else if (this.length != other.length) {
3 by Gustav Hartvigsson
* It works. :-)
213
        return this.length - other.length;
2 by Gustav Hartvigsson
* encountered a bug in Valac:
214
      }
215
      
216
      return 0;
217
    }
218
    
12 by Gustav Hartvigsson
* Made the C api better.
219
    [CCode (cname = "bit_field_info_compare")]
8 by Gustav Hartvigsson
* Fixed type : campare->compare.
220
    public static extern int static_compare (FieldInfo a, FieldInfo b);
221
    
2 by Gustav Hartvigsson
* encountered a bug in Valac:
222
    
223
    
224
    public bool overlap (FieldInfo other) {
225
      return (!((this.start < other.end) || (this.end > other.start)));
226
    }
227
    
12 by Gustav Hartvigsson
* Made the C api better.
228
    [CCode (cname = "bit_field_info_overlap")]
8 by Gustav Hartvigsson
* Fixed type : campare->compare.
229
    public static extern bool static_overlap (FieldInfo a, FieldInfo b);
2 by Gustav Hartvigsson
* encountered a bug in Valac:
230
    
231
    
232
    public string to_string () {
3 by Gustav Hartvigsson
* It works. :-)
233
      return "field_id: %i start: %i, end: %i, length: %i".printf (
234
                                                      this.field_id,
235
                                                      this.start,
2 by Gustav Hartvigsson
* encountered a bug in Valac:
236
                                                      this.end,
237
                                                      this.length);
238
    }
239
    
240
    /**
241
     * returns true on error;
242
     */
243
    public bool validate () {
3 by Gustav Hartvigsson
* It works. :-)
244
      var distance = this.end - this.start + 1;
2 by Gustav Hartvigsson
* encountered a bug in Valac:
245
      if (distance < 1 || distance != this.length) {
246
        return true;
247
      }
248
      return false;
249
    }
250
    
12 by Gustav Hartvigsson
* Made the C api better.
251
    [CCode (cname = "bit_field_info_validate")]
2 by Gustav Hartvigsson
* encountered a bug in Valac:
252
    public extern static bool static_validate (FieldInfo info);
253
    
254
    public uint16 generate_mask () {
255
      uint16 mask = 0;
256
      for (size_t i = 0; i < this.length; i++) {
3 by Gustav Hartvigsson
* It works. :-)
257
        mask >>= 1; // shit it over to the right one.
2 by Gustav Hartvigsson
* encountered a bug in Valac:
258
        mask += 0x8000; // set the left-most bit in the field
259
      }
260
      
3 by Gustav Hartvigsson
* It works. :-)
261
      // Shift over the mask to where it should start.
262
      mask >>= this.start; 
2 by Gustav Hartvigsson
* encountered a bug in Valac:
263
      
264
      return mask;
265
    }
266
    
12 by Gustav Hartvigsson
* Made the C api better.
267
    [CCode (cname = "bit_field_info_generate_mask")]
2 by Gustav Hartvigsson
* encountered a bug in Valac:
268
    public extern static uint16 static_generate_mask (FieldInfo info);
269
  }
270
  
3 by Gustav Hartvigsson
* It works. :-)
271
  public struct Type {
2 by Gustav Hartvigsson
* encountered a bug in Valac:
272
    FieldInfo[] fields;
273
    
274
    Type () {
275
        fields = new FieldInfo[16];
3 by Gustav Hartvigsson
* It works. :-)
276
        for (uint8 i = 0; i < 16; i++) {
277
          fields[i] = {255,255,255,255};
278
        }
2 by Gustav Hartvigsson
* encountered a bug in Valac:
279
    }
280
    
281
    public string to_string () {
282
      var sb = new GLib.StringBuilder ();
283
      
284
      sb.append (typeof (Type).name ())
285
        .append (": (\n");
286
      for (size_t i = 0; i < fields.length; i++) {
287
          sb.append ("\t (")
288
            .append (fields[i].to_string ())
289
            .append (")\n");
290
      }
291
      
292
      sb.append (")\n");
293
      return sb.str;
294
    }
3 by Gustav Hartvigsson
* It works. :-)
295
    
296
    public FieldInfo get_field_info (int field_id) {
297
      
298
      FieldInfo ii = {0};
299
      
300
      foreach (FieldInfo ij in fields) {
301
        if (ij.field_id == field_id) {
302
          ii = ij;
303
        }
304
      }
305
      
306
      return ii;
307
    }
308
    
2 by Gustav Hartvigsson
* encountered a bug in Valac:
309
  }
310
  
1 by Gustav Hartvigsson
start of project
311
}