Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtinfo / DtMmdb / btree_berkeley / bt_utils.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: bt_utils.c /main/3 1996/06/11 17:13:20 cde-hal $ */
24 /*-
25  * Copyright (c) 1990, 1993
26  *      The Regents of the University of California.  All rights reserved.
27  *
28  * This code is derived from software contributed to Berkeley by
29  * Mike Olson.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  * 1. Redistributions of source code must retain the above copyright
35  *    notice, this list of conditions and the following disclaimer.
36  * 2. Redistributions in binary form must reproduce the above copyright
37  *    notice, this list of conditions and the following disclaimer in the
38  *    documentation and/or other materials provided with the distribution.
39  * 3. All advertising materials mentioning features or use of this software
40  *    must display the following acknowledgement:
41  *      This product includes software developed by the University of
42  *      California, Berkeley and its contributors.
43  * 4. Neither the name of the University nor the names of its contributors
44  *    may be used to endorse or promote products derived from this software
45  *    without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57  * SUCH DAMAGE.
58  */
59
60 #if defined(LIBC_SCCS) && !defined(lint)
61 static char sccsid[] = "@(#)bt_utils.c  8.2 (Berkeley) 9/7/93";
62 #endif /* LIBC_SCCS and not lint */
63
64 #include <sys/param.h>
65
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69
70 #include <db.h>
71 #include "btree.h"
72
73 /*
74  * __BT_RET -- Build return key/data pair as a result of search or scan.
75  *
76  * Parameters:
77  *      t:      tree
78  *      d:      LEAF to be returned to the user.
79  *      key:    user's key structure (NULL if not to be filled in)
80  *      data:   user's data structure
81  *
82  * Returns:
83  *      RET_SUCCESS, RET_ERROR.
84  */
85 int
86 __bt_ret(t, e, key, data)
87         BTREE *t;
88         EPG *e;
89         DBT *key, *data;
90 {
91         register BLEAF *bl;
92         register void *p;
93
94         bl = GETBLEAF(e->page, e->index);
95
96         /*
97          * We always copy big keys/data to make them contigous.  Otherwise,
98          * we leave the page pinned and don't copy unless the user specified
99          * concurrent access.
100          */
101         if (bl->flags & P_BIGDATA) {
102                 if (__ovfl_get(t, bl->bytes + bl->ksize,
103                     &data->size, &t->bt_dbuf, &t->bt_dbufsz))
104                         return (RET_ERROR);
105                 data->data = t->bt_dbuf;
106         } else if (ISSET(t, B_DB_LOCK)) {
107                 /* Use +1 in case the first record retrieved is 0 length. */
108                 if (bl->dsize + 1 > t->bt_dbufsz) {
109                         if ((p = __fix_realloc(t->bt_dbuf, bl->dsize + 1)) == NULL)
110                                 return (RET_ERROR);
111                         t->bt_dbuf = p;
112                         t->bt_dbufsz = bl->dsize + 1;
113                 }
114                 memmove(t->bt_dbuf, bl->bytes + bl->ksize, bl->dsize);
115                 data->size = bl->dsize;
116                 data->data = t->bt_dbuf;
117         } else {
118                 data->size = bl->dsize;
119                 data->data = bl->bytes + bl->ksize;
120         }
121
122         if (key == NULL)
123                 return (RET_SUCCESS);
124
125         if (bl->flags & P_BIGKEY) {
126                 if (__ovfl_get(t, bl->bytes,
127                     &key->size, &t->bt_kbuf, &t->bt_kbufsz))
128                         return (RET_ERROR);
129                 key->data = t->bt_kbuf;
130         } else if (ISSET(t, B_DB_LOCK)) {
131                 if (bl->ksize > t->bt_kbufsz) {
132                         if ((p = __fix_realloc(t->bt_kbuf, bl->ksize)) == NULL)
133                                 return (RET_ERROR);
134                         t->bt_kbuf = p;
135                         t->bt_kbufsz = bl->ksize;
136                 }
137                 memmove(t->bt_kbuf, bl->bytes, bl->ksize);
138                 key->size = bl->ksize;
139                 key->data = t->bt_kbuf;
140         } else {
141                 key->size = bl->ksize;
142                 key->data = bl->bytes;
143         }
144         return (RET_SUCCESS);
145 }
146
147 /*
148  * __BT_CMP -- Compare a key to a given record.
149  *
150  * Parameters:
151  *      t:      tree
152  *      k1:     DBT pointer of first arg to comparison
153  *      e:      pointer to EPG for comparison
154  *
155  * Returns:
156  *      < 0 if k1 is < record
157  *      = 0 if k1 is = record
158  *      > 0 if k1 is > record
159  */
160 int
161 __bt_cmp(t, k1, e)
162         BTREE *t;
163         const DBT *k1;
164         EPG *e;
165 {
166         BINTERNAL *bi;
167         BLEAF *bl;
168         DBT k2;
169         PAGE *h;
170         void *bigkey;
171
172         /*
173          * The left-most key on internal pages, at any level of the tree, is
174          * guaranteed by the following code to be less than any user key.
175          * This saves us from having to update the leftmost key on an internal
176          * page when the user inserts a new key in the tree smaller than
177          * anything we've yet seen.
178          */
179         h = e->page;
180         if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
181                 return (1);
182
183         bigkey = NULL;
184         if (h->flags & P_BLEAF) {
185                 bl = GETBLEAF(h, e->index);
186                 if (bl->flags & P_BIGKEY)
187                         bigkey = bl->bytes;
188                 else {
189                         k2.data = bl->bytes;
190                         k2.size = bl->ksize;
191                 }
192         } else {
193                 bi = GETBINTERNAL(h, e->index);
194                 if (bi->flags & P_BIGKEY)
195                         bigkey = bi->bytes;
196                 else {
197                         k2.data = bi->bytes;
198                         k2.size = bi->ksize;
199                 }
200         }
201
202         if (bigkey) {
203                 if (__ovfl_get(t, bigkey,
204                     &k2.size, &t->bt_dbuf, &t->bt_dbufsz))
205                         return (RET_ERROR);
206                 k2.data = t->bt_dbuf;
207         }
208         return ((*t->bt_cmp)(k1, &k2));
209 }
210
211 /*
212  * __BT_DEFCMP -- Default comparison routine.
213  *
214  * Parameters:
215  *      a:      DBT #1
216  *      b:      DBT #2
217  *
218  * Returns:
219  *      < 0 if a is < b
220  *      = 0 if a is = b
221  *      > 0 if a is > b
222  */
223 int
224 __bt_defcmp(a, b)
225         const DBT *a, *b;
226 {
227         register u_char *p1, *p2;
228         register int diff, len;
229
230         len = MIN(a->size, b->size);
231         for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
232                 if (diff = *p1 - *p2)
233                         return (diff);
234         return (a->size - b->size);
235 }
236
237 /*
238  * __BT_DEFPFX -- Default prefix routine.
239  *
240  * Parameters:
241  *      a:      DBT #1
242  *      b:      DBT #2
243  *
244  * Returns:
245  *      Number of bytes needed to distinguish b from a.
246  */
247 int
248 __bt_defpfx(a, b)
249         const DBT *a, *b;
250 {
251         register u_char *p1, *p2;
252         register int len;
253         int cnt;
254
255         cnt = 1;
256         len = MIN(a->size, b->size);
257         for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
258                 if (*p1 != *p2)
259                         return (cnt);
260
261         /* a->size must be <= b->size, or they wouldn't be in this order. */
262         return (a->size < b->size ? a->size + 1 : a->size);
263 }