/+junk/vala-bit-field

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/%2Bjunk/vala-bit-field

« back to all changes in this revision

Viewing changes to src/bit_map.vala

  • Committer: Gustav Hartvigsson
  • Date: 2020-11-03 17:19:50 UTC
  • Revision ID: gustav.hartvigsson@gmail.com-20201103171950-u9cjz5g22bcrvmyd
* Fixed type : campare->compare.
* Fixed type for function alias.

Show diffs side-by-side

added added

removed removed

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