bt_utils.c revision 1.3 1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Mike Olson.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #if defined(LIBC_SCCS) && !defined(lint)
38 /*static char *sccsid = "from: @(#)bt_utils.c 8.1 (Berkeley) 6/4/93";*/
39 static char *rcsid = "$Id: bt_utils.c,v 1.3 1993/08/26 00:43:32 jtc Exp $";
40 #endif /* LIBC_SCCS and not lint */
41
42 #include <sys/param.h>
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include <db.h>
49 #include "btree.h"
50
51 /*
52 * __BT_RET -- Build return key/data pair as a result of search or scan.
53 *
54 * Parameters:
55 * t: tree
56 * d: LEAF to be returned to the user.
57 * key: user's key structure (NULL if not to be filled in)
58 * data: user's data structure
59 *
60 * Returns:
61 * RET_SUCCESS, RET_ERROR.
62 */
63 int
64 __bt_ret(t, e, key, data)
65 BTREE *t;
66 EPG *e;
67 DBT *key, *data;
68 {
69 register BLEAF *bl;
70 register void *p;
71
72 bl = GETBLEAF(e->page, e->index);
73
74 if (bl->flags & P_BIGDATA) {
75 if (__ovfl_get(t, bl->bytes + bl->ksize,
76 &data->size, &t->bt_dbuf, &t->bt_dbufsz))
77 return (RET_ERROR);
78 } else {
79 /* Use +1 in case the first record retrieved is 0 length. */
80 if (bl->dsize + 1 > t->bt_dbufsz) {
81 if ((p = realloc(t->bt_dbuf, bl->dsize + 1)) == NULL)
82 return (RET_ERROR);
83 t->bt_dbuf = p;
84 t->bt_dbufsz = bl->dsize + 1;
85 }
86 memmove(t->bt_dbuf, bl->bytes + bl->ksize, bl->dsize);
87 data->size = bl->dsize;
88 }
89 data->data = t->bt_dbuf;
90
91 if (key == NULL)
92 return (RET_SUCCESS);
93
94 if (bl->flags & P_BIGKEY) {
95 if (__ovfl_get(t, bl->bytes,
96 &key->size, &t->bt_kbuf, &t->bt_kbufsz))
97 return (RET_ERROR);
98 } else {
99 if (bl->ksize > t->bt_kbufsz) {
100 if ((p = realloc(t->bt_kbuf, bl->ksize)) == NULL)
101 return (RET_ERROR);
102 t->bt_kbuf = p;
103 t->bt_kbufsz = bl->ksize;
104 }
105 memmove(t->bt_kbuf, bl->bytes, bl->ksize);
106 key->size = bl->ksize;
107 }
108 key->data = t->bt_kbuf;
109 return (RET_SUCCESS);
110 }
111
112 /*
113 * __BT_CMP -- Compare a key to a given record.
114 *
115 * Parameters:
116 * t: tree
117 * k1: DBT pointer of first arg to comparison
118 * e: pointer to EPG for comparison
119 *
120 * Returns:
121 * < 0 if k1 is < record
122 * = 0 if k1 is = record
123 * > 0 if k1 is > record
124 */
125 int
126 __bt_cmp(t, k1, e)
127 BTREE *t;
128 const DBT *k1;
129 EPG *e;
130 {
131 BINTERNAL *bi;
132 BLEAF *bl;
133 DBT k2;
134 PAGE *h;
135 void *bigkey;
136
137 /*
138 * The left-most key on internal pages, at any level of the tree, is
139 * guaranteed by the following code to be less than any user key.
140 * This saves us from having to update the leftmost key on an internal
141 * page when the user inserts a new key in the tree smaller than
142 * anything we've yet seen.
143 */
144 h = e->page;
145 if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
146 return (1);
147
148 bigkey = NULL;
149 if (h->flags & P_BLEAF) {
150 bl = GETBLEAF(h, e->index);
151 if (bl->flags & P_BIGKEY)
152 bigkey = bl->bytes;
153 else {
154 k2.data = bl->bytes;
155 k2.size = bl->ksize;
156 }
157 } else {
158 bi = GETBINTERNAL(h, e->index);
159 if (bi->flags & P_BIGKEY)
160 bigkey = bi->bytes;
161 else {
162 k2.data = bi->bytes;
163 k2.size = bi->ksize;
164 }
165 }
166
167 if (bigkey) {
168 if (__ovfl_get(t, bigkey,
169 &k2.size, &t->bt_dbuf, &t->bt_dbufsz))
170 return (RET_ERROR);
171 k2.data = t->bt_dbuf;
172 }
173 return ((*t->bt_cmp)(k1, &k2));
174 }
175
176 /*
177 * __BT_DEFCMP -- Default comparison routine.
178 *
179 * Parameters:
180 * a: DBT #1
181 * b: DBT #2
182 *
183 * Returns:
184 * < 0 if a is < b
185 * = 0 if a is = b
186 * > 0 if a is > b
187 */
188 int
189 __bt_defcmp(a, b)
190 const DBT *a, *b;
191 {
192 register u_char *p1, *p2;
193 register int diff, len;
194
195 len = MIN(a->size, b->size);
196 for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
197 if (diff = *p1 - *p2)
198 return (diff);
199 return (a->size - b->size);
200 }
201
202 /*
203 * __BT_DEFPFX -- Default prefix routine.
204 *
205 * Parameters:
206 * a: DBT #1
207 * b: DBT #2
208 *
209 * Returns:
210 * Number of bytes needed to distinguish b from a.
211 */
212 int
213 __bt_defpfx(a, b)
214 const DBT *a, *b;
215 {
216 register u_char *p1, *p2;
217 register int len;
218 int cnt;
219
220 cnt = 1;
221 len = MIN(a->size, b->size);
222 for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
223 if (*p1 != *p2)
224 return (cnt);
225
226 /* a->size must be <= b->size, or they wouldn't be in this order. */
227 return (a->size < b->size ? a->size + 1 : a->size);
228 }
229