r3783: - don't use make proto for ldb anymore
[kamenim/samba.git] / source4 / lib / ldb / common / ldb_msg.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb message component utility functions
29  *
30  *  Description: functions for manipulating ldb_message structures
31  *
32  *  Author: Andrew Tridgell
33  */
34
35 #include "includes.h"
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38
39
40 /*
41   find an element in a message by attribute name
42 */
43 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, 
44                                                  const char *attr_name)
45 {
46         unsigned int i;
47         for (i=0;i<msg->num_elements;i++) {
48                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
49                         return &msg->elements[i];
50                 }
51         }
52         return NULL;
53 }
54
55 /*
56   see if two ldb_val structures contain exactly the same data
57   return 1 for a match, 0 for a mis-match
58 */
59 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
60 {
61         if (v1->length != v2->length) return 0;
62
63         if (v1->length == 0) return 1;
64
65         if (memcmp(v1->data, v2->data, v1->length) == 0) {
66                 return 1;
67         }
68
69         return 0;
70 }
71
72 /*
73   find a value in an element
74   assumes case sensitive comparison
75 */
76 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, 
77                                  struct ldb_val *val)
78 {
79         unsigned int i;
80         for (i=0;i<el->num_values;i++) {
81                 if (ldb_val_equal_exact(val, &el->values[i])) {
82                         return &el->values[i];
83                 }
84         }
85         return NULL;
86 }
87
88 /*
89   duplicate a ldb_val structure
90 */
91 struct ldb_val ldb_val_dup(struct ldb_context *ldb,
92                            const struct ldb_val *v)
93 {
94         struct ldb_val v2;
95         v2.length = v->length;
96         if (v->length == 0) {
97                 v2.data = NULL;
98                 return v2;
99         }
100
101         /* the +1 is to cope with buggy C library routines like strndup
102            that look one byte beyond */
103         v2.data = ldb_malloc(ldb, v->length+1);
104         if (!v2.data) {
105                 v2.length = 0;
106                 return v2;
107         }
108
109         memcpy(v2.data, v->data, v->length);
110         ((char *)v2.data)[v->length] = 0;
111         return v2;
112 }
113
114 /*
115   add an empty element to a message
116 */
117 int ldb_msg_add_empty(struct ldb_context *ldb,
118                       struct ldb_message *msg, const char *attr_name, int flags)
119 {
120         struct ldb_message_element *els;
121
122         els = ldb_realloc_p(ldb, msg->elements, 
123                             struct ldb_message_element, msg->num_elements+1);
124         if (!els) {
125                 errno = ENOMEM;
126                 return -1;
127         }
128
129         els[msg->num_elements].values = NULL;
130         els[msg->num_elements].num_values = 0;
131         els[msg->num_elements].flags = flags;
132         els[msg->num_elements].name = ldb_strdup(ldb, attr_name);
133         if (!els[msg->num_elements].name) {
134                 return -1;
135         }
136
137         msg->elements = els;
138         msg->num_elements++;
139
140         return 0;
141 }
142
143 /*
144   add an empty element to a message
145 */
146 int ldb_msg_add(struct ldb_context *ldb,
147                 struct ldb_message *msg, 
148                 const struct ldb_message_element *el, 
149                 int flags)
150 {
151         if (ldb_msg_add_empty(ldb, msg, el->name, flags) != 0) {
152                 return -1;
153         }
154
155         msg->elements[msg->num_elements-1] = *el;
156         msg->elements[msg->num_elements-1].flags = flags;
157
158         return 0;
159 }
160
161 /*
162   add a value to a message
163 */
164 int ldb_msg_add_value(struct ldb_context *ldb,
165                       struct ldb_message *msg, 
166                       const char *attr_name,
167                       struct ldb_val *val)
168 {
169         struct ldb_message_element *el;
170         struct ldb_val *vals;
171
172         el = ldb_msg_find_element(msg, attr_name);
173         if (!el) {
174                 ldb_msg_add_empty(ldb, msg, attr_name, 0);
175                 el = ldb_msg_find_element(msg, attr_name);
176         }
177         if (!el) {
178                 return -1;
179         }
180
181         vals = ldb_realloc_p(ldb, el->values, struct ldb_val, el->num_values+1);
182         if (!vals) {
183                 errno = ENOMEM;
184                 return -1;
185         }
186         el->values = vals;
187         el->values[el->num_values] = *val;
188         el->num_values++;
189
190         return 0;
191 }
192
193
194 /*
195   add a string element to a message
196 */
197 int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, 
198                        const char *attr_name, char *str)
199 {
200         struct ldb_val val;
201
202         val.data = str;
203         val.length = strlen(str);
204
205         return ldb_msg_add_value(ldb, msg, attr_name, &val);
206 }
207
208 /*
209   compare two ldb_message_element structures
210   assumes case senistive comparison
211 */
212 int ldb_msg_element_compare(struct ldb_message_element *el1, 
213                             struct ldb_message_element *el2)
214 {
215         unsigned int i;
216
217         if (el1->num_values != el2->num_values) {
218                 return el1->num_values - el2->num_values;
219         }
220
221         for (i=0;i<el1->num_values;i++) {
222                 if (!ldb_msg_find_val(el2, &el1->values[i])) {
223                         return -1;
224                 }
225         }
226
227         return 0;
228 }
229
230 /*
231   convenience functions to return common types from a message
232   these return the first value if the attribute is multi-valued
233 */
234 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name)
235 {
236         struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
237         if (!el || el->num_values == 0) {
238                 return NULL;
239         }
240         return &el->values[0];
241 }
242
243 int ldb_msg_find_int(const struct ldb_message *msg, 
244                      const char *attr_name,
245                      int default_value)
246 {
247         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
248         if (!v || !v->data) {
249                 return default_value;
250         }
251         return strtol(v->data, NULL, 0);
252 }
253
254 unsigned int ldb_msg_find_uint(const struct ldb_message *msg, 
255                                const char *attr_name,
256                                unsigned int default_value)
257 {
258         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
259         if (!v || !v->data) {
260                 return default_value;
261         }
262         return strtoul(v->data, NULL, 0);
263 }
264
265 int64_t ldb_msg_find_int64(const struct ldb_message *msg, 
266                            const char *attr_name,
267                            int64_t default_value)
268 {
269         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
270         if (!v || !v->data) {
271                 return default_value;
272         }
273         return strtoll(v->data, NULL, 0);
274 }
275
276 uint64_t ldb_msg_find_uint64(const struct ldb_message *msg, 
277                              const char *attr_name,
278                              uint64_t default_value)
279 {
280         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
281         if (!v || !v->data) {
282                 return default_value;
283         }
284         return strtoull(v->data, NULL, 0);
285 }
286
287 double ldb_msg_find_double(const struct ldb_message *msg, 
288                            const char *attr_name,
289                            double default_value)
290 {
291         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
292         if (!v || !v->data) {
293                 return default_value;
294         }
295         return strtod(v->data, NULL);
296 }
297
298 const char *ldb_msg_find_string(const struct ldb_message *msg, 
299                                 const char *attr_name,
300                                 const char *default_value)
301 {
302         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
303         if (!v || !v->data) {
304                 return default_value;
305         }
306         return v->data;
307 }