data.c

00001 /*
00002  * lib/data.c           Abstract Data
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup core
00014  * @defgroup data Abstract Data
00015  * @{
00016  */
00017 
00018 #include <netlink-local.h>
00019 #include <netlink/netlink.h>
00020 #include <netlink/utils.h>
00021 #include <linux/socket.h>
00022 
00023 /**
00024  * @name General
00025  * @{
00026  */
00027 
00028 /**
00029  * Allocate a new abstract data object.
00030  * @arg buf             Data buffer containing the actual data.
00031  * @arg size            Size of data buffer.
00032  *
00033  * Allocates a new abstract data and copies the specified data
00034  * buffer into the new handle.
00035  * 
00036  * @return Newly allocated data handle or NULL
00037  */
00038 struct nl_data *nl_data_alloc(void *buf, size_t size)
00039 {
00040         struct nl_data *data;
00041 
00042         data = calloc(1, sizeof(*data));
00043         if (!data)
00044                 goto errout;
00045 
00046         data->d_data = calloc(1, size);
00047         if (!data->d_data) {
00048                 free(data);
00049                 goto errout;
00050         }
00051 
00052         data->d_size = size;
00053 
00054         if (buf)
00055                 memcpy(data->d_data, buf, size);
00056 
00057         return data;
00058 errout:
00059         return NULL;
00060 }
00061 
00062 /**
00063  * Allocate abstract data object based on netlink attribute.
00064  * @arg nla             Netlink attribute of unspecific type.
00065  *
00066  * Allocates a new abstract data and copies the payload of the
00067  * attribute to the abstract data object.
00068  * 
00069  * @see nla_data_alloc
00070  * @return Newly allocated data handle or NULL
00071  */
00072 struct nl_data *nl_data_alloc_attr(struct nlattr *nla)
00073 {
00074         return nl_data_alloc(nla_data(nla), nla_len(nla));
00075 }
00076 
00077 /**
00078  * Clone an abstract data object.
00079  * @arg src             Abstract data object
00080  *
00081  * @return Cloned object or NULL
00082  */
00083 struct nl_data *nl_data_clone(struct nl_data *src)
00084 {
00085         return nl_data_alloc(src->d_data, src->d_size);
00086 }
00087 
00088 /**
00089  * Append data to an abstract data object.
00090  * @arg data            Abstract data object.
00091  * @arg buf             Data buffer containing the data to be appended.
00092  * @arg size            Size of data to be apppended.
00093  *
00094  * Reallocates an abstract data and copies the specified data
00095  * buffer into the new handle.
00096  * 
00097  * @return 0 on success or a negative error code
00098  */
00099 int nl_data_append(struct nl_data *data, void *buf, size_t size)
00100 {
00101         if (size < 0)
00102                 BUG();
00103 
00104         if (size > 0) {
00105                 data->d_data = realloc(data->d_data, data->d_size + size);
00106                 if (!data->d_data)
00107                         return -NLE_NOMEM;
00108 
00109                 if (buf)
00110                         memcpy(data->d_data + data->d_size, buf, size);
00111                 else
00112                         memset(data->d_data + data->d_size, 0, size);
00113 
00114                 data->d_size += size;
00115         }
00116 
00117         return 0;
00118 }
00119 
00120 /**
00121  * Free an abstract data object.
00122  * @arg data            Abstract data object.
00123  */
00124 void nl_data_free(struct nl_data *data)
00125 {
00126         if (data)
00127                 free(data->d_data);
00128 
00129         free(data);
00130 }
00131 
00132 /** @} */
00133 
00134 /**
00135  * @name Attribute Access
00136  * @{
00137  */
00138 
00139 /**
00140  * Get data buffer of abstract data object.
00141  * @arg data            Abstract data object.
00142  * @return Data buffer or NULL if empty.
00143  */
00144 void *nl_data_get(struct nl_data *data)
00145 {
00146         return data->d_size > 0 ? data->d_data : NULL;
00147 }
00148 
00149 /**
00150  * Get size of data buffer of abstract data object.
00151  * @arg data            Abstract data object.
00152  * @return Size of data buffer.
00153  */
00154 size_t nl_data_get_size(struct nl_data *data)
00155 {
00156         return data->d_size;
00157 }
00158 
00159 /** @} */
00160 
00161 /**
00162  * @name Misc
00163  * @{
00164  */
00165 
00166 /**
00167  * Compare two abstract data objects.
00168  * @arg a               Abstract data object.
00169  * @arg b               Another abstract data object.
00170  * @return An integer less than, equal to, or greater than zero if
00171  *         a is found, respectively, to be less than, to match, or
00172  *         be greater than b.
00173  */
00174 int nl_data_cmp(struct nl_data *a, struct nl_data *b)
00175 {
00176         void *a_ = nl_data_get(a);
00177         void *b_ = nl_data_get(b);
00178 
00179         if (a_ && b_)
00180                 return memcmp(a_, b_, nl_data_get_size(a));
00181         else
00182                 return -1;
00183 }
00184 
00185 /** @} */
00186 /** @} */