1/*
2 * lib/data.c		Abstract Data
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 core
14 * @defgroup data Abstract Data
15 * @{
16 */
17
18#include <netlink-local.h>
19#include <netlink/netlink.h>
20#include <netlink/utils.h>
21#include <linux/socket.h>
22
23/**
24 * @name General
25 * @{
26 */
27
28/**
29 * Allocate a new abstract data object.
30 * @arg buf		Data buffer containing the actual data.
31 * @arg size		Size of data buffer.
32 *
33 * Allocates a new abstract data and copies the specified data
34 * buffer into the new handle.
35 *
36 * @return Newly allocated data handle or NULL
37 */
38struct nl_data *nl_data_alloc(void *buf, size_t size)
39{
40	struct nl_data *data;
41
42	data = calloc(1, sizeof(*data));
43	if (!data)
44		goto errout;
45
46	data->d_data = calloc(1, size);
47	if (!data->d_data) {
48		free(data);
49		goto errout;
50	}
51
52	data->d_size = size;
53
54	if (buf)
55		memcpy(data->d_data, buf, size);
56
57	return data;
58errout:
59	return NULL;
60}
61
62/**
63 * Allocate abstract data object based on netlink attribute.
64 * @arg nla		Netlink attribute of unspecific type.
65 *
66 * Allocates a new abstract data and copies the payload of the
67 * attribute to the abstract data object.
68 *
69 * @see nla_data_alloc
70 * @return Newly allocated data handle or NULL
71 */
72struct nl_data *nl_data_alloc_attr(struct nlattr *nla)
73{
74	return nl_data_alloc(nla_data(nla), nla_len(nla));
75}
76
77/**
78 * Clone an abstract data object.
79 * @arg src		Abstract data object
80 *
81 * @return Cloned object or NULL
82 */
83struct nl_data *nl_data_clone(struct nl_data *src)
84{
85	return nl_data_alloc(src->d_data, src->d_size);
86}
87
88/**
89 * Append data to an abstract data object.
90 * @arg data		Abstract data object.
91 * @arg buf		Data buffer containing the data to be appended.
92 * @arg size		Size of data to be apppended.
93 *
94 * Reallocates an abstract data and copies the specified data
95 * buffer into the new handle.
96 *
97 * @return 0 on success or a negative error code
98 */
99int nl_data_append(struct nl_data *data, void *buf, size_t size)
100{
101	if (size < 0)
102		BUG();
103
104	if (size > 0) {
105		data->d_data = realloc(data->d_data, data->d_size + size);
106		if (!data->d_data)
107			return -NLE_NOMEM;
108
109		if (buf)
110			memcpy(data->d_data + data->d_size, buf, size);
111		else
112			memset(data->d_data + data->d_size, 0, size);
113
114		data->d_size += size;
115	}
116
117	return 0;
118}
119
120/**
121 * Free an abstract data object.
122 * @arg data		Abstract data object.
123 */
124void nl_data_free(struct nl_data *data)
125{
126	if (data)
127		free(data->d_data);
128
129	free(data);
130}
131
132/** @} */
133
134/**
135 * @name Attribute Access
136 * @{
137 */
138
139/**
140 * Get data buffer of abstract data object.
141 * @arg data		Abstract data object.
142 * @return Data buffer or NULL if empty.
143 */
144void *nl_data_get(struct nl_data *data)
145{
146	return data->d_size > 0 ? data->d_data : NULL;
147}
148
149/**
150 * Get size of data buffer of abstract data object.
151 * @arg data		Abstract data object.
152 * @return Size of data buffer.
153 */
154size_t nl_data_get_size(struct nl_data *data)
155{
156	return data->d_size;
157}
158
159/** @} */
160
161/**
162 * @name Misc
163 * @{
164 */
165
166/**
167 * Compare two abstract data objects.
168 * @arg a		Abstract data object.
169 * @arg b		Another abstract data object.
170 * @return An integer less than, equal to, or greater than zero if
171 *         a is found, respectively, to be less than, to match, or
172 *         be greater than b.
173 */
174int nl_data_cmp(struct nl_data *a, struct nl_data *b)
175{
176	void *a_ = nl_data_get(a);
177	void *b_ = nl_data_get(b);
178
179	if (a_ && b_)
180		return memcmp(a_, b_, nl_data_get_size(a));
181	else
182		return -1;
183}
184
185/** @} */
186/** @} */
187