xref: /original-bsd/lib/libc/db/btree/bt_utils.c (revision 95ecee29)
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  * %sccs.include.redist.c%
9  */
10 
11 #if defined(LIBC_SCCS) && !defined(lint)
12 static char sccsid[] = "@(#)bt_utils.c	8.2 (Berkeley) 09/07/93";
13 #endif /* LIBC_SCCS and not lint */
14 
15 #include <sys/param.h>
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include <db.h>
22 #include "btree.h"
23 
24 /*
25  * __BT_RET -- Build return key/data pair as a result of search or scan.
26  *
27  * Parameters:
28  *	t:	tree
29  *	d:	LEAF to be returned to the user.
30  *	key:	user's key structure (NULL if not to be filled in)
31  *	data:	user's data structure
32  *
33  * Returns:
34  *	RET_SUCCESS, RET_ERROR.
35  */
36 int
37 __bt_ret(t, e, key, data)
38 	BTREE *t;
39 	EPG *e;
40 	DBT *key, *data;
41 {
42 	register BLEAF *bl;
43 	register void *p;
44 
45 	bl = GETBLEAF(e->page, e->index);
46 
47 	/*
48 	 * We always copy big keys/data to make them contigous.  Otherwise,
49 	 * we leave the page pinned and don't copy unless the user specified
50 	 * concurrent access.
51 	 */
52 	if (bl->flags & P_BIGDATA) {
53 		if (__ovfl_get(t, bl->bytes + bl->ksize,
54 		    &data->size, &t->bt_dbuf, &t->bt_dbufsz))
55 			return (RET_ERROR);
56 		data->data = t->bt_dbuf;
57 	} else if (ISSET(t, B_DB_LOCK)) {
58 		/* Use +1 in case the first record retrieved is 0 length. */
59 		if (bl->dsize + 1 > t->bt_dbufsz) {
60 			if ((p = realloc(t->bt_dbuf, bl->dsize + 1)) == NULL)
61 				return (RET_ERROR);
62 			t->bt_dbuf = p;
63 			t->bt_dbufsz = bl->dsize + 1;
64 		}
65 		memmove(t->bt_dbuf, bl->bytes + bl->ksize, bl->dsize);
66 		data->size = bl->dsize;
67 		data->data = t->bt_dbuf;
68 	} else {
69 		data->size = bl->dsize;
70 		data->data = bl->bytes + bl->ksize;
71 	}
72 
73 	if (key == NULL)
74 		return (RET_SUCCESS);
75 
76 	if (bl->flags & P_BIGKEY) {
77 		if (__ovfl_get(t, bl->bytes,
78 		    &key->size, &t->bt_kbuf, &t->bt_kbufsz))
79 			return (RET_ERROR);
80 		key->data = t->bt_kbuf;
81 	} else if (ISSET(t, B_DB_LOCK)) {
82 		if (bl->ksize > t->bt_kbufsz) {
83 			if ((p = realloc(t->bt_kbuf, bl->ksize)) == NULL)
84 				return (RET_ERROR);
85 			t->bt_kbuf = p;
86 			t->bt_kbufsz = bl->ksize;
87 		}
88 		memmove(t->bt_kbuf, bl->bytes, bl->ksize);
89 		key->size = bl->ksize;
90 		key->data = t->bt_kbuf;
91 	} else {
92 		key->size = bl->ksize;
93 		key->data = bl->bytes;
94 	}
95 	return (RET_SUCCESS);
96 }
97 
98 /*
99  * __BT_CMP -- Compare a key to a given record.
100  *
101  * Parameters:
102  *	t:	tree
103  *	k1:	DBT pointer of first arg to comparison
104  *	e:	pointer to EPG for comparison
105  *
106  * Returns:
107  *	< 0 if k1 is < record
108  *	= 0 if k1 is = record
109  *	> 0 if k1 is > record
110  */
111 int
112 __bt_cmp(t, k1, e)
113 	BTREE *t;
114 	const DBT *k1;
115 	EPG *e;
116 {
117 	BINTERNAL *bi;
118 	BLEAF *bl;
119 	DBT k2;
120 	PAGE *h;
121 	void *bigkey;
122 
123 	/*
124 	 * The left-most key on internal pages, at any level of the tree, is
125 	 * guaranteed by the following code to be less than any user key.
126 	 * This saves us from having to update the leftmost key on an internal
127 	 * page when the user inserts a new key in the tree smaller than
128 	 * anything we've yet seen.
129 	 */
130 	h = e->page;
131 	if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
132 		return (1);
133 
134 	bigkey = NULL;
135 	if (h->flags & P_BLEAF) {
136 		bl = GETBLEAF(h, e->index);
137 		if (bl->flags & P_BIGKEY)
138 			bigkey = bl->bytes;
139 		else {
140 			k2.data = bl->bytes;
141 			k2.size = bl->ksize;
142 		}
143 	} else {
144 		bi = GETBINTERNAL(h, e->index);
145 		if (bi->flags & P_BIGKEY)
146 			bigkey = bi->bytes;
147 		else {
148 			k2.data = bi->bytes;
149 			k2.size = bi->ksize;
150 		}
151 	}
152 
153 	if (bigkey) {
154 		if (__ovfl_get(t, bigkey,
155 		    &k2.size, &t->bt_dbuf, &t->bt_dbufsz))
156 			return (RET_ERROR);
157 		k2.data = t->bt_dbuf;
158 	}
159 	return ((*t->bt_cmp)(k1, &k2));
160 }
161 
162 /*
163  * __BT_DEFCMP -- Default comparison routine.
164  *
165  * Parameters:
166  *	a:	DBT #1
167  *	b: 	DBT #2
168  *
169  * Returns:
170  *	< 0 if a is < b
171  *	= 0 if a is = b
172  *	> 0 if a is > b
173  */
174 int
175 __bt_defcmp(a, b)
176 	const DBT *a, *b;
177 {
178 	register u_char *p1, *p2;
179 	register int diff, len;
180 
181 	len = MIN(a->size, b->size);
182 	for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
183 		if (diff = *p1 - *p2)
184 			return (diff);
185 	return (a->size - b->size);
186 }
187 
188 /*
189  * __BT_DEFPFX -- Default prefix routine.
190  *
191  * Parameters:
192  *	a:	DBT #1
193  *	b: 	DBT #2
194  *
195  * Returns:
196  *	Number of bytes needed to distinguish b from a.
197  */
198 int
199 __bt_defpfx(a, b)
200 	const DBT *a, *b;
201 {
202 	register u_char *p1, *p2;
203 	register int len;
204 	int cnt;
205 
206 	cnt = 1;
207 	len = MIN(a->size, b->size);
208 	for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
209 		if (*p1 != *p2)
210 			return (cnt);
211 
212 	/* a->size must be <= b->size, or they wouldn't be in this order. */
213 	return (a->size < b->size ? a->size + 1 : a->size);
214 }
215