4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/types.h>
28 #include <sys/sysmacros.h>
33 #include <dt_strtab.h>
37 dt_strtab_grow(dt_strtab_t
*sp
)
41 if ((ptr
= malloc(sp
->str_bufsz
)) == NULL
)
44 bufs
= reallocarray(sp
->str_bufs
, sp
->str_nbufs
+ 1, sizeof (char *));
54 sp
->str_bufs
[sp
->str_nbufs
- 1] = sp
->str_ptr
;
60 dt_strtab_create(size_t bufsz
)
62 dt_strtab_t
*sp
= malloc(sizeof (dt_strtab_t
));
63 uint_t nbuckets
= _dtrace_strbuckets
;
70 bzero(sp
, sizeof (dt_strtab_t
));
71 sp
->str_hash
= malloc(nbuckets
* sizeof (dt_strhash_t
*));
73 if (sp
->str_hash
== NULL
)
76 bzero(sp
->str_hash
, nbuckets
* sizeof (dt_strhash_t
*));
77 sp
->str_hashsz
= nbuckets
;
81 sp
->str_bufsz
= bufsz
;
85 if (dt_strtab_grow(sp
) == -1)
88 *sp
->str_ptr
++ = '\0';
92 dt_strtab_destroy(sp
);
97 dt_strtab_destroy(dt_strtab_t
*sp
)
99 dt_strhash_t
*hp
, *hq
;
102 for (i
= 0; i
< sp
->str_hashsz
; i
++) {
103 for (hp
= sp
->str_hash
[i
]; hp
!= NULL
; hp
= hq
) {
109 for (i
= 0; i
< sp
->str_nbufs
; i
++)
110 free(sp
->str_bufs
[i
]);
119 dt_strtab_hash(const char *key
, size_t *len
)
125 for (p
= key
; *p
!= '\0'; p
++, n
++) {
128 if ((g
= (h
& 0xf0000000)) != 0) {
141 dt_strtab_compare(dt_strtab_t
*sp
, dt_strhash_t
*hp
,
142 const char *str
, size_t len
)
144 ulong_t b
= hp
->str_buf
;
145 const char *buf
= hp
->str_data
;
150 if (buf
== sp
->str_bufs
[b
] + sp
->str_bufsz
)
151 buf
= sp
->str_bufs
[++b
];
153 resid
= sp
->str_bufs
[b
] + sp
->str_bufsz
- buf
;
156 if ((rv
= strncmp(buf
, str
, n
)) != 0)
168 dt_strtab_copyin(dt_strtab_t
*sp
, const char *str
, size_t len
)
170 char *old_p
= sp
->str_ptr
;
171 ulong_t old_n
= sp
->str_nbufs
;
173 ulong_t b
= sp
->str_nbufs
- 1;
177 if (sp
->str_ptr
== sp
->str_bufs
[b
] + sp
->str_bufsz
) {
178 if (dt_strtab_grow(sp
) == -1)
183 resid
= sp
->str_bufs
[b
] + sp
->str_bufsz
- sp
->str_ptr
;
185 bcopy(str
, sp
->str_ptr
, n
);
195 while (sp
->str_nbufs
!= old_n
)
196 free(sp
->str_bufs
[--sp
->str_nbufs
]);
203 dt_strtab_index(dt_strtab_t
*sp
, const char *str
)
209 if (str
== NULL
|| str
[0] == '\0')
210 return (0); /* we keep a \0 at offset 0 to simplify things */
212 h
= dt_strtab_hash(str
, &len
) % sp
->str_hashsz
;
214 for (hp
= sp
->str_hash
[h
]; hp
!= NULL
; hp
= hp
->str_next
) {
215 if (dt_strtab_compare(sp
, hp
, str
, len
+ 1) == 0)
216 return (hp
->str_off
);
223 dt_strtab_insert(dt_strtab_t
*sp
, const char *str
)
230 if ((off
= dt_strtab_index(sp
, str
)) != -1)
233 h
= dt_strtab_hash(str
, &len
) % sp
->str_hashsz
;
236 * Create a new hash bucket, initialize it, and insert it at the front
237 * of the hash chain for the appropriate bucket.
239 if ((hp
= malloc(sizeof (dt_strhash_t
))) == NULL
)
242 hp
->str_data
= sp
->str_ptr
;
243 hp
->str_buf
= sp
->str_nbufs
- 1;
244 hp
->str_off
= sp
->str_size
;
246 hp
->str_next
= sp
->str_hash
[h
];
249 * Now copy the string data into our buffer list, and then update
250 * the global counts of strings and bytes. Return str's byte offset.
252 if (dt_strtab_copyin(sp
, str
, len
+ 1) == -1)
256 sp
->str_size
+= len
+ 1;
257 sp
->str_hash
[h
] = hp
;
259 return (hp
->str_off
);
263 dt_strtab_size(const dt_strtab_t
*sp
)
265 return (sp
->str_size
);
269 dt_strtab_write(const dt_strtab_t
*sp
, dt_strtab_write_f
*func
, void *private)
271 ssize_t res
, total
= 0;
275 for (i
= 0; i
< sp
->str_nbufs
; i
++, total
+= res
) {
276 if (i
== sp
->str_nbufs
- 1)
277 n
= sp
->str_ptr
- sp
->str_bufs
[i
];
281 if ((res
= func(sp
->str_bufs
[i
], n
, total
, private)) <= 0)
285 if (total
== 0 && sp
->str_size
!= 0)