Merge pull request #580 from wigyori/cc-libpcap
[15.05/openwrt.git] / package / libs / libnl-tiny / src / object.c
1 /*
2  * lib/object.c         Generic Cacheable Object
3  *
4  *      This library is free software; you can redistribute it and/or
5  *      modify it under the terms of the GNU Lesser General Public
6  *      License as published by the Free Software Foundation version 2.1
7  *      of the License.
8  *
9  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
10  */
11
12 /**
13  * @ingroup cache
14  * @defgroup object Object
15  * @{
16  */
17
18 #include <netlink-local.h>
19 #include <netlink/netlink.h>
20 #include <netlink/cache.h>
21 #include <netlink/object.h>
22 #include <netlink/utils.h>
23
24 static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
25 {
26         if (!obj->ce_ops)
27                 BUG();
28
29         return obj->ce_ops;
30 }
31
32 /**
33  * @name Object Creation/Deletion
34  * @{
35  */
36
37 /**
38  * Allocate a new object of kind specified by the operations handle
39  * @arg ops             cache operations handle
40  * @return The new object or NULL
41  */
42 struct nl_object *nl_object_alloc(struct nl_object_ops *ops)
43 {
44         struct nl_object *new;
45
46         if (ops->oo_size < sizeof(*new))
47                 BUG();
48
49         new = calloc(1, ops->oo_size);
50         if (!new)
51                 return NULL;
52
53         new->ce_refcnt = 1;
54         nl_init_list_head(&new->ce_list);
55
56         new->ce_ops = ops;
57         if (ops->oo_constructor)
58                 ops->oo_constructor(new);
59
60         NL_DBG(4, "Allocated new object %p\n", new);
61
62         return new;
63 }
64
65 struct nl_derived_object {
66         NLHDR_COMMON
67         char data;
68 };
69
70 /**
71  * Allocate a new object and copy all data from an existing object
72  * @arg obj             object to inherite data from
73  * @return The new object or NULL.
74  */
75 struct nl_object *nl_object_clone(struct nl_object *obj)
76 {
77         struct nl_object *new;
78         struct nl_object_ops *ops = obj_ops(obj);
79         int doff = offsetof(struct nl_derived_object, data);
80         int size;
81
82         new = nl_object_alloc(ops);
83         if (!new)
84                 return NULL;
85
86         size = ops->oo_size - doff;
87         if (size < 0)
88                 BUG();
89
90         new->ce_ops = obj->ce_ops;
91         new->ce_msgtype = obj->ce_msgtype;
92
93         if (size)
94                 memcpy((void *)new + doff, (void *)obj + doff, size);
95
96         if (ops->oo_clone) {
97                 if (ops->oo_clone(new, obj) < 0) {
98                         nl_object_free(new);
99                         return NULL;
100                 }
101         } else if (size && ops->oo_free_data)
102                 BUG();
103
104         return new;
105 }
106
107 /**
108  * Free a cacheable object
109  * @arg obj             object to free
110  *
111  * @return 0 or a negative error code.
112  */
113 void nl_object_free(struct nl_object *obj)
114 {
115         struct nl_object_ops *ops = obj_ops(obj);
116
117         if (obj->ce_refcnt > 0)
118                 NL_DBG(1, "Warning: Freeing object in use...\n");
119
120         if (obj->ce_cache)
121                 nl_cache_remove(obj);
122
123         if (ops->oo_free_data)
124                 ops->oo_free_data(obj);
125
126         free(obj);
127
128         NL_DBG(4, "Freed object %p\n", obj);
129 }
130
131 /** @} */
132
133 /**
134  * @name Reference Management
135  * @{
136  */
137
138 /** @} */
139
140 /**
141  * @name Utillities
142  * @{
143  */
144
145 /** @} */
146
147 /** @} */