/simpletypesystem/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/simpletypesystem/trunk
5.2.7 by Gustav Hartvigsson
* Switched licence to a more permisive one.
1
/*
2
Copyright (c) 2013-2014 Gustav Hartvigsson
3
4
Permission is hereby granted, free of charge, to any person obtaining a copy
5
of this software and associated documentation files (the "Software"), to deal
6
in the Software without restriction, including without limitation the rights
7
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
copies of the Software, and to permit persons to whom the Software is
9
furnished to do so, subject to the following conditions:
10
11
The above copyright notice and this permission notice shall be included in
12
all copies or substantial portions of the Software.
13
14
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
THE SOFTWARE.
21
*/
3 by Gustav Hartvigsson
Fixed a few things...
22
23
#include "Error.h"
24
#include <stdlib.h>
25
#include <string.h>
26
#include <stdio.h>
22 by Gustav Hartvigsson
* Made code compile
27
#include <assert.h>
39 by Gustav Hartvigsson
* Added "check" target for testing.
28
#include "utils.h"
100 by Gustav Hartvigsson
* Fixed README.
29
#include "LinkedList.h"
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
30
#include "DynamicArray.h"
31
32
33
/* **************************************************************************
34
 *********************** INTERNALS ******************************************
35
 **************************************************************************** */
36
37
typedef
38
struct SErrorItem {
81 by Gustav Hartvigsson
* Re arranged members of structs to prevent struct fragmentation and padding.
39
  schar * message;
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
40
  SErrorDomain error_domain;
41
  sint error_type;
100 by Gustav Hartvigsson
* Fixed README.
42
} SErrorItem;
43
44
struct SError {
45
  SLinkedList * error_list; /* SLinkedList<SErrorItem *> */
3 by Gustav Hartvigsson
Fixed a few things...
46
};
47
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
48
49
typedef
50
struct SErrorDomainItem {
51
  SErrorDomain domain;
52
  SErrorDomainToString to_string_func;
53
  schar * domain_name;
54
} SErrorDomainItem;
55
56
static
57
SDynamicArray *
58
_internal_s_error_domain_list = NULL; /* <SErrorDomainItem *> */
59
60
void
61
_internal_s_error_domain_item_free (SErrorDomainItem * self);
62
63
void
64
_internal_s_error_item_free (SErrorItem * self);
65
66
void
67
_internal_s_error_list_for_each_item (SDynamicArray * in_array,
68
                                        SErrorItem * item,
69
                                        SDynamicArray * out_array);
70
71
schar *
72
s_default_error_domain_to_string (sint error_id, schar * msg) {
73
  schar * ret_val = s_string_new_fmt ("Error %d (%s): %s",
74
                                      error_id,
75
                                      s_default_error_get_name (error_id),
76
                                      msg);
77
  return ret_val;
78
}
79
80
schar *
81
s_default_error_get_name (SDefaultErrorType k) {
82
  return SDefaultErrorTypeName[k];
83
}
84
85
/* **************************************************************************
86
 ************************** SError ******************************************
87
 **************************************************************************** */
88
104 by Gustav Hartvigsson
* Passing arguments can not be initialised from within a function...
89
SError *
90
s_error_new (void) {
91
  SError * self = malloc (sizeof (SError));
108 by Gustav Hartvigsson
libssts:
92
  self->error_list = s_linked_list_new (FREEFUNC (_internal_s_error_item_free));
104 by Gustav Hartvigsson
* Passing arguments can not be initialised from within a function...
93
  return self;
94
}
95
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
96
void
108 by Gustav Hartvigsson
libssts:
97
s_error_append (SError * self ,
98
                sint error, const char * message,
99
                SErrorDomain error_domain) {
104 by Gustav Hartvigsson
* Passing arguments can not be initialised from within a function...
100
  assert (self != NULL);
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
101
  SErrorItem * item = malloc (sizeof (SErrorItem));
102
103
  item->message = s_string_new (message);
104
  item->error_type = error;
105
  item->error_domain = error_domain;
106
107
  s_linked_list_append (self->error_list, item);
108
}
109
108 by Gustav Hartvigsson
libssts:
110
sboolean
111
s_error_has_error (SError * self) {
112
  if (self != NULL) {
113
    if (s_linked_list_get_current (self->error_list)) {
114
      return TRUE;
115
    }
116
  }
117
  return FALSE;
118
}
119
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
120
SDynamicArray *
121
s_error_to_string_array (SError * self) {
104 by Gustav Hartvigsson
* Passing arguments can not be initialised from within a function...
122
  assert (self != NULL);
123
124
  size_t out_arr_len = s_linked_list_len (self->error_list);
125
126
  SDynamicArray * ret_val = s_dynamic_array_new (out_arr_len, NULL);
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
127
128
  s_linked_list_for_each (self->error_list,
129
                          FOREACHFUNC(_internal_s_error_list_for_each_item),
130
                          ret_val);
131
132
  return ret_val;
3 by Gustav Hartvigsson
Fixed a few things...
133
}
134
61 by Gustav Hartvigsson
* Made the code more easy to read.
135
void
108 by Gustav Hartvigsson
libssts:
136
s_error_free (SError * self) {
101 by Gustav Hartvigsson
* Re-Added the inlines...
137
  s_linked_list_free (self->error_list, TRUE);
100 by Gustav Hartvigsson
* Fixed README.
138
  free (self);
3 by Gustav Hartvigsson
Fixed a few things...
139
}
140
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
141
void
142
s_error_teardown () {
108 by Gustav Hartvigsson
libssts:
143
  s_dbg_print ("Taring down error system....");
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
144
  if (_internal_s_error_domain_list) {
145
    s_dynamic_array_free (_internal_s_error_domain_list, TRUE);
146
  }
104 by Gustav Hartvigsson
* Passing arguments can not be initialised from within a function...
147
  s_dbg_print ("Done taring down error system.");
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
148
}
149
150
151
152
/* **************************************************************************
153
 *********************** SErrorDomain ***************************************
154
 **************************************************************************** */
155
156
SErrorDomain
157
s_error_get_domain (const schar * name, SErrorDomainToString to_string_func) {
158
  SErrorDomainItem * item = NULL;
159
160
  if (strlen (name) == 0 || to_string_func == NULL) {
161
    s_err_print ("Domain name or to_string_func not set.\n");
162
    return -2;
163
  }
164
165
  if (!(_internal_s_error_domain_list)) {
104 by Gustav Hartvigsson
* Passing arguments can not be initialised from within a function...
166
    s_dbg_print ("Array does not exist, lets crete it!");
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
167
    _internal_s_error_domain_list =
168
          s_dynamic_array_new (S_ERROR_DOMAIN_RANGE_MAX,
169
          FREEFUNC (_internal_s_error_domain_item_free));
170
    // The default key is always 0
171
    item = malloc (sizeof (SErrorDomainItem));
172
    item->domain = 0;
173
    item->to_string_func = s_default_error_domain_to_string;
174
    item->domain_name = s_string_new ("default");
175
    s_dynamic_array_set (_internal_s_error_domain_list, 0, item);
176
  }
177
178
  if (s_string_is_equal (name, "default")) {
179
    if (to_string_func != s_default_error_domain_to_string) {
180
      s_err_print ("Trying to override the default error domain to string "
181
                   "callback.\n"
182
                   "This is not allowed! \n");
183
      return -1;
184
    }
185
    return 0;
186
  }
187
188
  /* We hash the domain name and see it the domain exists. */
189
  SErrorDomain domain = s_hash (name) % S_ERROR_DOMAIN_RANGE_MAX;
190
191
  SErrorDomainItem * item_2 = (SErrorDomainItem *) s_dynamic_array_get
192
                              (_internal_s_error_domain_list, domain);
193
  if ((item_2) == NULL) {
194
    /*
195
     * The item dose not exist in the array, lets just add it.
196
     */
197
    item = malloc (sizeof (SErrorDomainItem));
198
    item->domain = domain;
199
    item->to_string_func = to_string_func;
200
    item->domain_name = s_string_new (name);
201
202
    s_dynamic_array_set (_internal_s_error_domain_list ,domain, item);
203
204
    return domain;
205
  } else {
108 by Gustav Hartvigsson
libssts:
206
    /* We got something. See it it is correct */
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
207
    if (s_string_is_equal(item_2->domain_name, name)) {
108 by Gustav Hartvigsson
libssts:
208
      if (item_2->to_string_func != to_string_func) {
209
        s_err_print ("Trying to overwrite the to string handler"
210
                     "for error domain %s, this is not allowd.",
211
                     name);
212
        return -1;
213
      }
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
214
      return domain;
215
    }
216
    /*
217
     * We must now check each item untill we reach a NULL.
218
     */
219
    for (sint i = domain;
220
           i <= s_dynamic_array_size (_internal_s_error_domain_list);
221
             i++) {
222
      item_2 = (SErrorDomainItem *) s_dynamic_array_get (_internal_s_error_domain_list, i);
223
      if ((item_2) == NULL) {
224
        break; // This jumps out of the loop and to the for-loop below.
225
      } else {
226
        if (s_string_is_equal (item_2->domain_name, name)) {
227
          if (item_2->to_string_func != to_string_func) {
228
            s_err_print ("Trying to override to string function for error "
229
                         "domain %s.\nThis is not allowed!\n", name);
230
            return -1;
231
          } else {
232
            return i;
233
          }
234
        }
235
      }
236
    }
237
  }
238
239
  /*
240
   * The error domain does not exist.
241
   */
242
  for (/* domain */;
243
       domain <= s_dynamic_array_size (_internal_s_error_domain_list) + 1;
244
       domain++) {
245
    if (!(s_dynamic_array_get(_internal_s_error_domain_list ,domain))) {
246
      item = malloc (sizeof (SErrorDomainItem));
247
      item->domain = domain;
248
      item->domain_name = s_string_new (name);
249
      item->to_string_func = to_string_func;
250
      return domain;
251
    }
252
  }
253
254
  s_err_print ("Reaching a place where it should not reach. This is a sign "
255
               "that the devil has been messing with time and space.\n");
256
  print_backtrace ();
257
258
  return -666;
259
}
260
261
262
263
/* **************************************************************************
264
 *********************** INTERNALS ******************************************
265
 **************************************************************************** */
266
267
void
268
_internal_s_error_domain_item_free (SErrorDomainItem * self) {
108 by Gustav Hartvigsson
libssts:
269
  s_dbg_print ("(SErrorDomainItem) Freeing: %d, %s",
270
               self->domain,
271
               self->domain_name);
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
272
  free (self->domain_name);
273
  free (self);
274
}
275
276
void
277
_internal_s_error_list_for_each_item (SDynamicArray * in_array,
278
                                      SErrorItem * item,
279
                                      SDynamicArray * out_array) {
280
  SErrorDomainItem * domain_item = s_dynamic_array_get (
281
                                          _internal_s_error_domain_list,
282
                                          item->error_domain);
104 by Gustav Hartvigsson
* Passing arguments can not be initialised from within a function...
283
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
284
  SErrorDomainToString to_string_func = domain_item->to_string_func;
285
  s_dynamic_array_append (out_array, to_string_func (item->error_type,
286
                                                     item->message));
287
}
288
289
void
290
_internal_s_error_item_free (SErrorItem * self) {
108 by Gustav Hartvigsson
libssts:
291
  s_dbg_print ("Running free on errori item!");
103 by Gustav Hartvigsson
* General cleanup/make it pritty.
292
  free (self->message);
293
  free (self);
294
}