r1374: Fix signed/unsigned warnings (actually found by g++) after unsigned int
[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
37
38 /*
39   find an element in a message by attribute name
40 */
41 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg, 
42                                                  const char *attr_name)
43 {
44         unsigned int i;
45         for (i=0;i<msg->num_elements;i++) {
46                 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
47                         return &msg->elements[i];
48                 }
49         }
50         return NULL;
51 }
52
53 /*
54   see if two ldb_val structures contain exactly the same data
55   return 1 for a match, 0 for a mis-match
56 */
57 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
58 {
59         if (v1->length != v2->length) return 0;
60
61         if (v1->length == 0) return 1;
62
63         if (memcmp(v1->data, v2->data, v1->length) == 0) {
64                 return 1;
65         }
66
67         return 0;
68 }
69
70 /*
71   find a value in an element
72   assumes case sensitive comparison
73 */
74 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el, 
75                                  struct ldb_val *val)
76 {
77         unsigned int i;
78         for (i=0;i<el->num_values;i++) {
79                 if (ldb_val_equal_exact(val, &el->values[i])) {
80                         return &el->values[i];
81                 }
82         }
83         return NULL;
84 }
85
86
87 /*
88   add an empty element to a message
89 */
90 int ldb_msg_add_empty(struct ldb_context *ldb,
91                       struct ldb_message *msg, const char *attr_name, int flags)
92 {
93         struct ldb_message_element *els;
94
95         els = ldb_realloc_p(ldb, msg->elements, 
96                             struct ldb_message_element, msg->num_elements+1);
97         if (!els) {
98                 errno = ENOMEM;
99                 return -1;
100         }
101
102         els[msg->num_elements].values = NULL;
103         els[msg->num_elements].num_values = 0;
104         els[msg->num_elements].flags = flags;
105         els[msg->num_elements].name = ldb_strdup(ldb, attr_name);
106         if (!els[msg->num_elements].name) {
107                 return -1;
108         }
109
110         msg->elements = els;
111         msg->num_elements++;
112
113         return 0;
114 }
115
116 /*
117   add an empty element to a message
118 */
119 int ldb_msg_add(struct ldb_context *ldb,
120                 struct ldb_message *msg, 
121                 const struct ldb_message_element *el, 
122                 int flags)
123 {
124         if (ldb_msg_add_empty(ldb, msg, el->name, flags) != 0) {
125                 return -1;
126         }
127
128         msg->elements[msg->num_elements-1] = *el;
129         msg->elements[msg->num_elements-1].flags = flags;
130
131         return 0;
132 }
133
134 /*
135   add a value to a message
136 */
137 int ldb_msg_add_value(struct ldb_context *ldb,
138                       struct ldb_message *msg, 
139                       const char *attr_name,
140                       struct ldb_val *val)
141 {
142         struct ldb_message_element *el;
143         struct ldb_val *vals;
144
145         el = ldb_msg_find_element(msg, attr_name);
146         if (!el) {
147                 ldb_msg_add_empty(ldb, msg, attr_name, 0);
148                 el = ldb_msg_find_element(msg, attr_name);
149         }
150         if (!el) {
151                 return -1;
152         }
153
154         vals = ldb_realloc_p(ldb, el->values, struct ldb_val, el->num_values+1);
155         if (!vals) {
156                 errno = ENOMEM;
157                 return -1;
158         }
159         el->values = vals;
160         el->values[el->num_values] = *val;
161         el->num_values++;
162
163         return 0;
164 }
165
166
167 /*
168   add a string element to a message
169 */
170 int ldb_msg_add_string(struct ldb_context *ldb, struct ldb_message *msg, 
171                        const char *attr_name, char *str)
172 {
173         struct ldb_val val;
174
175         val.data = str;
176         val.length = strlen(str);
177
178         return ldb_msg_add_value(ldb, msg, attr_name, &val);
179 }
180
181 /*
182   compare two ldb_message_element structures
183   assumes case senistive comparison
184 */
185 int ldb_msg_element_compare(struct ldb_message_element *el1, 
186                             struct ldb_message_element *el2)
187 {
188         unsigned int i;
189
190         if (el1->num_values != el2->num_values) {
191                 return el1->num_values - el2->num_values;
192         }
193
194         for (i=0;i<el1->num_values;i++) {
195                 if (!ldb_msg_find_val(el2, &el1->values[i])) {
196                         return -1;
197                 }
198         }
199
200         return 0;
201 }
202
203 /*
204   convenience functions to return common types from a message
205   these return the first value if the attribute is multi-valued
206 */
207 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name)
208 {
209         struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
210         if (!el || el->num_values == 0) {
211                 return NULL;
212         }
213         return &el->values[0];
214 }
215
216 int ldb_msg_find_int(const struct ldb_message *msg, 
217                      const char *attr_name,
218                      int default_value)
219 {
220         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
221         if (!v || !v->data) {
222                 return default_value;
223         }
224         return strtol(v->data, NULL, 0);
225 }
226
227 unsigned int ldb_msg_find_uint(const struct ldb_message *msg, 
228                                const char *attr_name,
229                                unsigned int default_value)
230 {
231         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
232         if (!v || !v->data) {
233                 return default_value;
234         }
235         return strtoul(v->data, NULL, 0);
236 }
237
238 int64_t ldb_msg_find_int64(const struct ldb_message *msg, 
239                            const char *attr_name,
240                            int64_t default_value)
241 {
242         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
243         if (!v || !v->data) {
244                 return default_value;
245         }
246         return strtoll(v->data, NULL, 0);
247 }
248
249 uint64_t ldb_msg_find_uint64(const struct ldb_message *msg, 
250                              const char *attr_name,
251                              uint64_t default_value)
252 {
253         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
254         if (!v || !v->data) {
255                 return default_value;
256         }
257         return strtoull(v->data, NULL, 0);
258 }
259
260 double ldb_msg_find_double(const struct ldb_message *msg, 
261                            const char *attr_name,
262                            double default_value)
263 {
264         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
265         if (!v || !v->data) {
266                 return default_value;
267         }
268         return strtod(v->data, NULL);
269 }
270
271 const char *ldb_msg_find_string(const struct ldb_message *msg, 
272                                 const char *attr_name,
273                                 const char *default_value)
274 {
275         const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
276         if (!v || !v->data) {
277                 return default_value;
278         }
279         return v->data;
280 }