~lib2geom-hackers/lib2geom/trunk

« back to all changes in this revision

Viewing changes to object.cpp

  • Committer: njh
  • Date: 2006-05-22 11:50:24 UTC
  • Revision ID: svn-v4:4601daaa-0314-0410-9a8b-c964a3c23b6b:trunk/lib2geom:1
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define __NR_OBJECT_C__
 
2
 
 
3
/*
 
4
 * RGBA display list system for inkscape
 
5
 *
 
6
 * Authors:
 
7
 *   Lauris Kaplinski <lauris@kaplinski.com>
 
8
 *   MenTaLguY <mental@rydia.net>
 
9
 *
 
10
 * This code is in public domain
 
11
 */
 
12
 
 
13
#include <string.h>
 
14
#include <stdio.h>
 
15
 
 
16
#include <libnr/nr-macros.h>
 
17
 
 
18
#include "nr-object.h"
 
19
 
 
20
unsigned int nr_emit_fail_warning(const gchar *file, unsigned int line, const gchar *method, const gchar *expr)
 
21
{
 
22
    fprintf (stderr, "File %s line %d (%s): Assertion %s failed\n", file, line, method, expr);
 
23
    return 1;
 
24
}
 
25
 
 
26
/* NRObject */
 
27
 
 
28
static NRObjectClass **classes = NULL;
 
29
static unsigned int classes_len = 0;
 
30
static unsigned int classes_size = 0;
 
31
 
 
32
NRType nr_type_is_a(NRType type, NRType test)
 
33
{
 
34
    nr_return_val_if_fail(type < classes_len, FALSE);
 
35
    nr_return_val_if_fail(test < classes_len, FALSE);
 
36
 
 
37
    NRObjectClass *c = classes[type];
 
38
 
 
39
    while (c) {
 
40
        if (c->type == test) {
 
41
            return TRUE;
 
42
        }
 
43
        c = c->parent;
 
44
    }
 
45
 
 
46
    return FALSE;
 
47
}
 
48
 
 
49
void const *nr_object_check_instance_cast(void const *ip, NRType tc)
 
50
{
 
51
    nr_return_val_if_fail(ip != NULL, NULL);
 
52
    nr_return_val_if_fail(nr_type_is_a(((NRObject const *) ip)->klass->type, tc), ip);
 
53
    return ip;
 
54
}
 
55
 
 
56
unsigned int nr_object_check_instance_type(void const *ip, NRType tc)
 
57
{
 
58
    if (ip == NULL) {
 
59
        return FALSE;
 
60
    }
 
61
    
 
62
    return nr_type_is_a(((NRObject const *) ip)->klass->type, tc);
 
63
}
 
64
 
 
65
NRType nr_object_register_type(NRType parent,
 
66
                               gchar const *name,
 
67
                               unsigned int csize,
 
68
                               unsigned int isize,
 
69
                               void (* cinit) (NRObjectClass *),
 
70
                               void (* iinit) (NRObject *))
 
71
{
 
72
    if (classes_len >= classes_size) {
 
73
        classes_size += 32;
 
74
        classes = nr_renew (classes, NRObjectClass *, classes_size);
 
75
        if (classes_len == 0) {
 
76
            classes[0] = NULL;
 
77
            classes_len = 1;
 
78
        }
 
79
    }
 
80
 
 
81
    NRType const type = classes_len;
 
82
    classes_len += 1;
 
83
 
 
84
    classes[type] = (NRObjectClass*) new char[csize];
 
85
    NRObjectClass *c = classes[type];
 
86
 
 
87
    /* FIXME: is this necessary? */
 
88
    memset(c, 0, csize);
 
89
 
 
90
    if (classes[parent]) {
 
91
        memcpy(c, classes[parent], classes[parent]->csize);
 
92
    }
 
93
 
 
94
    c->type = type;
 
95
    c->parent = classes[parent];
 
96
    c->name = strdup(name);
 
97
    c->csize = csize;
 
98
    c->isize = isize;
 
99
    c->cinit = cinit;
 
100
    c->iinit = iinit;
 
101
    
 
102
    c->cinit(c);
 
103
    
 
104
    return type;
 
105
}
 
106
 
 
107
static void nr_object_class_init (NRObjectClass *klass);
 
108
static void nr_object_init (NRObject *object);
 
109
static void nr_object_finalize (NRObject *object);
 
110
 
 
111
NRType nr_object_get_type()
 
112
{
 
113
    static NRType type = 0;
 
114
 
 
115
    if (!type) {
 
116
        type = nr_object_register_type (0,
 
117
                                        "NRObject",
 
118
                                        sizeof (NRObjectClass),
 
119
                                        sizeof (NRObject),
 
120
                                        (void (*) (NRObjectClass *)) nr_object_class_init,
 
121
                                        (void (*) (NRObject *)) nr_object_init);
 
122
    }
 
123
    
 
124
    return type;
 
125
}
 
126
 
 
127
static void nr_object_class_init(NRObjectClass *c)
 
128
{
 
129
    c->finalize = nr_object_finalize;
 
130
    c->cpp_ctor = NRObject::invoke_ctor<NRObject>;
 
131
}
 
132
 
 
133
static void nr_object_init (NRObject *object)
 
134
{
 
135
}
 
136
 
 
137
static void nr_object_finalize (NRObject *object)
 
138
{
 
139
}
 
140
 
 
141
/* Dynamic lifecycle */
 
142
 
 
143
static void nr_class_tree_object_invoke_init(NRObjectClass *c, NRObject *object)
 
144
{
 
145
    if (c->parent) {
 
146
        nr_class_tree_object_invoke_init(c->parent, object);
 
147
    }
 
148
    c->iinit (object);
 
149
}
 
150
 
 
151
namespace {
 
152
 
 
153
void finalize_object(void *base, void *)
 
154
{
 
155
    NRObject *object = reinterpret_cast<NRObject *>(base);
 
156
    object->klass->finalize(object);
 
157
    object->~NRObject();
 
158
}
 
159
 
 
160
}
 
161
 
 
162
NRObject *NRObject::alloc(NRType type)
 
163
{
 
164
    nr_return_val_if_fail (type < classes_len, NULL);
 
165
 
 
166
    NRObjectClass *c = classes[type];
 
167
 
 
168
    if ( c->parent && c->cpp_ctor == c->parent->cpp_ctor ) {
 
169
        g_error("Cannot instantiate NRObject class %s which has not registered a C++ constructor\n", c->name);
 
170
    }
 
171
 
 
172
    NRObject *object = reinterpret_cast<NRObject *>(
 
173
        ::operator new(c->isize, Inkscape::GC::SCANNED, Inkscape::GC::AUTO,
 
174
                       &finalize_object, NULL)
 
175
    );
 
176
    memset(object, 0xf0, c->isize);
 
177
 
 
178
    object->klass = c;
 
179
    c->cpp_ctor(object);
 
180
    nr_class_tree_object_invoke_init (c, object);
 
181
 
 
182
    return object;
 
183
}
 
184
 
 
185
/* NRActiveObject */
 
186
 
 
187
static void nr_active_object_class_init(NRActiveObjectClass *c);
 
188
static void nr_active_object_init(NRActiveObject *object);
 
189
static void nr_active_object_finalize(NRObject *object);
 
190
 
 
191
static NRObjectClass *parent_class;
 
192
 
 
193
NRType nr_active_object_get_type()
 
194
{
 
195
    static NRType type = 0;
 
196
    if (!type) {
 
197
        type = nr_object_register_type (NR_TYPE_OBJECT,
 
198
                                        "NRActiveObject",
 
199
                                        sizeof (NRActiveObjectClass),
 
200
                                        sizeof (NRActiveObject),
 
201
                                        (void (*) (NRObjectClass *)) nr_active_object_class_init,
 
202
                                        (void (*) (NRObject *)) nr_active_object_init);
 
203
    }
 
204
    return type;
 
205
}
 
206
 
 
207
static void nr_active_object_class_init(NRActiveObjectClass *c)
 
208
{
 
209
    NRObjectClass *object_class = (NRObjectClass *) c;
 
210
 
 
211
    parent_class = object_class->parent;
 
212
 
 
213
    object_class->finalize = nr_active_object_finalize;
 
214
    object_class->cpp_ctor = NRObject::invoke_ctor<NRActiveObject>;
 
215
}
 
216
 
 
217
static void nr_active_object_init(NRActiveObject *object)
 
218
{
 
219
}
 
220
 
 
221
static void nr_active_object_finalize(NRObject *object)
 
222
{
 
223
    NRActiveObject *aobject = (NRActiveObject *) object;
 
224
 
 
225
    if (aobject->callbacks) {
 
226
        for (unsigned int i = 0; i < aobject->callbacks->length; i++) {
 
227
            NRObjectListener *listener = aobject->callbacks->listeners + i;
 
228
            if ( listener->vector->dispose ) {
 
229
                listener->vector->dispose(object, listener->data);
 
230
            }
 
231
        }
 
232
        free (aobject->callbacks);
 
233
    }
 
234
 
 
235
    ((NRObjectClass *) (parent_class))->finalize(object);
 
236
}
 
237
 
 
238
void nr_active_object_add_listener(NRActiveObject *object,
 
239
                                   const NRObjectEventVector *vector,
 
240
                                   unsigned int size,
 
241
                                   void *data)
 
242
{
 
243
    if (!object->callbacks) {
 
244
        object->callbacks = (NRObjectCallbackBlock*) malloc(sizeof(NRObjectCallbackBlock));
 
245
        object->callbacks->size = 1;
 
246
        object->callbacks->length = 0;
 
247
    }
 
248
    
 
249
    if (object->callbacks->length >= object->callbacks->size) {
 
250
        int newsize = object->callbacks->size << 1;
 
251
        object->callbacks = (NRObjectCallbackBlock *)
 
252
            realloc(object->callbacks, sizeof(NRObjectCallbackBlock) + (newsize - 1) * sizeof (NRObjectListener));
 
253
        object->callbacks->size = newsize;
 
254
    }
 
255
    
 
256
    NRObjectListener *listener = object->callbacks->listeners + object->callbacks->length;
 
257
    listener->vector = vector;
 
258
    listener->size = size;
 
259
    listener->data = data;
 
260
    object->callbacks->length += 1;
 
261
}
 
262
 
 
263
void nr_active_object_remove_listener_by_data(NRActiveObject *object, void *data)
 
264
{
 
265
    if (object->callbacks == NULL) {
 
266
        return;
 
267
    }
 
268
    
 
269
    for (unsigned i = 0; i < object->callbacks->length; i++) {
 
270
        NRObjectListener *listener = object->callbacks->listeners + i;
 
271
        if ( listener->data == data ) {
 
272
            object->callbacks->length -= 1;
 
273
            if ( object->callbacks->length < 1 ) {
 
274
                free(object->callbacks);
 
275
                object->callbacks = NULL;
 
276
            } else if ( object->callbacks->length != i ) {
 
277
                *listener = object->callbacks->listeners[object->callbacks->length];
 
278
            }
 
279
            return;
 
280
        }
 
281
    }
 
282
}
 
283
 
 
284
 
 
285
 
 
286
/*
 
287
  Local Variables:
 
288
  mode:c++
 
289
  c-file-style:"stroustrup"
 
290
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
291
  indent-tabs-mode:nil
 
292
  fill-column:99
 
293
  End:
 
294
*/
 
295
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :