2 * Copyright (c) 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
30 #define KVBUF_CHUNK 256
33 * kvbuf_t is a list of key/value dictionaries.
35 * First 4 bytes are the number of dictionaries.
36 * For each dictionary, first 4 bytes is the key / value list count.
37 * For each value list, first 4 bytes is the list length.
38 * Keys and values are a 4-byte length followed by a nul-terminated string
40 * When the databuf needs to grow, we add memory in KVBUF_CHUNK size
41 * increments to reduce malloc / realloc activity.
42 * The _size variable stores the actual allocated size.
43 * The datalen variable stores the used data size.
45 * The _dict variable holds an offset from the start of the buffer
46 * to the "current" dictionary. kvbuf_reset() resets this,
47 * and kvbuf_next_dict() bumps the offset so that databuf + _dict
48 * points to the next dictionary.
50 * The _key variable holds an offset from the start of the buffer
51 * to the "current" key. kvbuf_reset() resets this, and
52 * kvbuf_next_key() bumps the offset so that databuf + _key
53 * points to the next key.
55 * The _val variable holds an offset from the start of the buffer
56 * to the "current" value. kvbuf_reset() resets this, and
57 * kvbuf_next_val() bumps the offset so that databuf + _val
58 * points to the next value.
60 * The cache_entry_list_to_kvbuf() routine contains the only
61 * code that builds an array.
66 * kvbuf_query is a simple utility for constructing a
67 * kvbuf with a single dictionary. The format string may
68 * contain the chars "k", "s", "i", and "u". "k" denotes a key
69 * (keys are always strings), "s" denotes a string value,
70 * "i" denotes a 32 bit signed int, and "u" denotes an unsigned.
72 __private_extern__ kvbuf_t
*
73 kvbuf_query(char *fmt
, ...)
76 char *arg
, *f
, str
[32];
81 if (fmt
== NULL
) return NULL
;
84 if (kv
== NULL
) return NULL
;
89 for (f
= fmt
; (*f
) != '\0'; f
++)
93 arg
= va_arg(ap
, char *);
94 kvbuf_add_key(kv
, arg
);
98 arg
= va_arg(ap
, char *);
99 kvbuf_add_val(kv
, arg
);
103 iarg
= va_arg(ap
, int32_t);
104 snprintf(str
, sizeof(str
), "%d", iarg
);
105 kvbuf_add_val(kv
, str
);
109 uarg
= va_arg(ap
,uint32_t);
110 snprintf(str
, sizeof(str
), "%u", uarg
);
111 kvbuf_add_val(kv
, str
);
120 kvbuf_query_key_val(const char *key
, const char *val
)
123 uint32_t x
, kl
, vl
, vc
;
126 if (key
== NULL
) return NULL
;
128 kl
= strlen(key
) + 1;
135 vl
= strlen(val
) + 1;
139 kv
= (kvbuf_t
*)calloc(1, sizeof(kvbuf_t
));
140 if (kv
== NULL
) return NULL
;
142 kv
->_size
= (5 * sizeof(uint32_t)) + kl
+ vl
;
143 kv
->datalen
= kv
->_size
;
145 kv
->databuf
= calloc(1, kv
->_size
);
146 if (kv
->databuf
== NULL
)
156 memcpy(p
, &x
, sizeof(uint32_t));
157 p
+= sizeof(uint32_t);
160 memcpy(p
, &x
, sizeof(uint32_t));
161 p
+= sizeof(uint32_t);
165 memcpy(p
, &x
, sizeof(uint32_t));
166 p
+= sizeof(uint32_t);
172 /* number of values */
174 memcpy(p
, &x
, sizeof(uint32_t));
175 p
+= sizeof(uint32_t);
181 memcpy(p
, &x
, sizeof(uint32_t));
182 p
+= sizeof(uint32_t);
191 __private_extern__ kvbuf_t
*
192 kvbuf_query_key_int(const char *key
, int32_t i
)
196 snprintf(str
, sizeof(str
), "%d", i
);
197 return kvbuf_query_key_val(key
, str
);
200 __private_extern__ kvbuf_t
*
201 kvbuf_query_key_uint(const char *key
, uint32_t u
)
205 snprintf(str
, sizeof(str
), "%u", u
);
206 return kvbuf_query_key_val(key
, str
);
210 kvbuf_new_zone(malloc_zone_t
*zone
)
214 if (zone
== NULL
) return NULL
;
216 kv
= (kvbuf_t
*)malloc_zone_calloc(zone
, 1, sizeof(kvbuf_t
));
217 if (kv
== NULL
) return NULL
;
219 kv
->_size
= KVBUF_START_SIZE
;
220 kv
->databuf
= malloc_zone_calloc(zone
, 1, kv
->_size
);
221 if (kv
->databuf
== NULL
)
227 kv
->datalen
= sizeof(uint32_t);
228 kv
->_dict
= kv
->datalen
;
236 return kvbuf_new_zone(malloc_default_zone());
240 kvbuf_init_zone(malloc_zone_t
*zone
, char *buffer
, uint32_t length
)
244 if (zone
== NULL
) return NULL
;
246 kv
= (kvbuf_t
*)malloc_zone_calloc(zone
, 1, sizeof(kvbuf_t
));
247 if (kv
== NULL
) return NULL
;
250 kv
->datalen
= length
;
251 kv
->databuf
= malloc_zone_calloc(zone
, 1, length
);
252 if (kv
->databuf
== NULL
)
259 memcpy(kv
->databuf
, buffer
, length
);
266 kvbuf_init(char *buffer
, uint32_t length
)
268 return kvbuf_init_zone(malloc_default_zone(), buffer
, length
);
272 kvbuf_grow(kvbuf_t
*kv
, uint32_t delta
)
277 if (kv
== NULL
) return;
278 if (delta
== 0) return;
280 if (kv
->databuf
== NULL
) delta
+= sizeof(uint32_t);
282 n
= (delta
+ KVBUF_CHUNK
- 1) / KVBUF_CHUNK
;
283 newlen
= kv
->datalen
+ (n
* KVBUF_CHUNK
);
285 if (newlen
<= kv
->_size
) return;
289 if (kv
->databuf
== NULL
)
291 kv
->databuf
= calloc(1, kv
->_size
);
292 if (kv
->databuf
== NULL
)
294 memset(kv
, 0, sizeof(kvbuf_t
));
298 kv
->datalen
= sizeof(uint32_t);
299 kv
->_dict
= sizeof(uint32_t);
303 kv
->databuf
= reallocf(kv
->databuf
, kv
->_size
);
304 if (kv
->databuf
== NULL
)
306 memset(kv
, 0, sizeof(kvbuf_t
));
310 p
= kv
->databuf
+ kv
->datalen
;
311 memset(p
, 0, kv
->_size
- kv
->datalen
);
316 kvbuf_add_dict(kvbuf_t
*kv
)
319 uint32_t x
, dict_count
;
321 if (kv
== NULL
) return;
323 /* Add a key count */
324 kvbuf_grow(kv
, sizeof(uint32_t));
325 if (kv
->databuf
== NULL
) return;
327 kv
->_dict
= kv
->datalen
;
328 kv
->datalen
+= sizeof(uint32_t);
330 kv
->_key
= kv
->datalen
;
334 /* increment and rewrite the dict count */
338 memcpy(&x
, p
, sizeof(uint32_t));
339 dict_count
= ntohl(x
);
342 x
= htonl(dict_count
);
343 memcpy(p
, &x
, sizeof(uint32_t));
347 kvbuf_add_key(kvbuf_t
*kv
, const char *key
)
349 uint32_t kl
, x
, key_count
, delta
;
352 if (kv
== NULL
) return;
353 if (key
== NULL
) return;
355 kl
= strlen(key
) + 1;
357 /* Grow to hold key len, key, and value list count. */
358 delta
= (2 * sizeof(uint32_t)) + kl
;
359 kvbuf_grow(kv
, delta
);
361 if (kv
->databuf
== NULL
) return;
363 /* increment and rewrite the key count for the current dictionary */
364 p
= kv
->databuf
+ kv
->_dict
;
367 memcpy(&x
, p
, sizeof(uint32_t));
368 key_count
= ntohl(x
);
370 if (key_count
== 0) kv
->_key
= kv
->_dict
+ sizeof(uint32_t);
371 else kv
->_key
= kv
->datalen
;
374 x
= htonl(key_count
);
375 memcpy(p
, &x
, sizeof(uint32_t));
377 /* append key to data buffer */
378 p
= kv
->databuf
+ kv
->datalen
;
381 memcpy(p
, &x
, sizeof(uint32_t));
382 p
+= sizeof(uint32_t);
386 kv
->_vlist
= kv
->datalen
+ sizeof(uint32_t) + kl
;
389 memcpy(p
, &x
, sizeof(uint32_t));
391 kv
->datalen
+= delta
;
392 kv
->_val
= kv
->datalen
;
396 kvbuf_add_val_len(kvbuf_t
*kv
, const char *val
, uint32_t len
)
398 uint32_t x
, val_count
, delta
;
401 if (kv
== NULL
) return;
402 if (val
== NULL
) return;
403 if (len
== 0) return;
405 /* Grow to hold val len and value. */
406 delta
= sizeof(uint32_t) + len
;
407 kvbuf_grow(kv
, delta
);
409 if (kv
->databuf
== NULL
) return;
411 /* increment and rewrite the value count for the value_list dictionary */
412 p
= kv
->databuf
+ kv
->_vlist
;
415 memcpy(&x
, p
, sizeof(uint32_t));
416 val_count
= ntohl(x
);
418 x
= htonl(val_count
);
419 memcpy(p
, &x
, sizeof(uint32_t));
421 /* append val to data buffer */
422 p
= kv
->databuf
+ kv
->_val
;
425 memcpy(p
, &x
, sizeof(uint32_t));
426 p
+= sizeof(uint32_t);
430 kv
->datalen
+= delta
;
431 kv
->_val
= kv
->datalen
;
435 * WARNING! Kludge Alert!
437 * This call just looks for the buffer length encoded into a serialized kvbuf_t,
438 * which preceeds a pointer to a key or value. Obviously, calling it with anything
439 * other than a pointer value which is embedded in a kvbuf_t is asking for trouble.
442 kvbuf_get_len(const char *p
)
447 memcpy(&x
, p
- sizeof(uint32_t), sizeof(uint32_t));
452 kvbuf_add_val(kvbuf_t
*kv
, const char *val
)
454 if (kv
== NULL
) return;
455 if (val
== NULL
) return;
457 kvbuf_add_val_len(kv
, val
, strlen(val
) + 1);
461 kvbuf_make_purgeable(kvbuf_t
*kv
)
463 if (kv
== NULL
) return;
465 if (kv
->databuf
!= NULL
) malloc_make_purgeable(kv
->databuf
);
469 kvbuf_make_nonpurgeable(kvbuf_t
*kv
)
471 if (kv
== NULL
) return 0;
474 * malloc_make_nonpurgeable returns 0 even if memory was not
475 * allocated from the purgeable zone, so this is safe to call.
477 if ((kv
->databuf
== NULL
) || (malloc_make_nonpurgeable(kv
->databuf
) == 0)) return 0;
479 /* return non-zero since something failed */
484 kvbuf_free(kvbuf_t
*kv
)
486 if (kv
== NULL
) return;
488 if (kv
->databuf
!= NULL
) free(kv
->databuf
);
489 memset(kv
, 0, sizeof(kvbuf_t
));
493 /* appends a kvbuf to an existing kvbuf */
495 kvbuf_append_kvbuf(kvbuf_t
*kv
, const kvbuf_t
*kv2
)
497 uint32_t curr_count
, new_count
, temp
;
499 if (kv
== NULL
) return;
500 if (kv2
== NULL
) return;
505 memcpy(&temp
, kv
->databuf
, sizeof(uint32_t));
506 curr_count
= ntohl(temp
);
508 memcpy(&temp
, kv2
->databuf
, sizeof(uint32_t));
509 new_count
= ntohl(temp
);
512 if (new_count
== 0) return;
514 /* add the dictionary count to the current dictionary counts */
515 curr_count
+= new_count
;
517 temp
= htonl(curr_count
);
518 memcpy(kv
->databuf
, &temp
, sizeof(uint32_t));
520 /* grow the current buffer so we can append the new buffer */
521 temp
= kv2
->datalen
- sizeof(uint32_t);
523 kvbuf_grow(kv
, temp
);
525 memcpy(kv
->databuf
+ kv
->datalen
, kv2
->databuf
+ sizeof(uint32_t), temp
);
529 /* returns number of dictionaries */
531 kvbuf_reset(kvbuf_t
*kv
)
535 if (kv
== NULL
) return 0;
536 if (kv
->databuf
== NULL
) return 0;
543 if (kv
->datalen
< sizeof(uint32_t)) return 0;
546 memcpy(&x
, kv
->databuf
, sizeof(uint32_t));
550 /* advance to next dictionary, returns key count */
552 kvbuf_next_dict(kvbuf_t
*kv
)
554 uint32_t x
, k
, v
, kcount
, vcount
, kl
, vl
;
557 if (kv
== NULL
) return 0;
558 if (kv
->databuf
== NULL
) return 0;
567 if (kv
->datalen
< sizeof(uint32_t)) return 0;
568 kv
->_dict
= sizeof(uint32_t);
570 if (kv
->datalen
< (kv
->_dict
+ sizeof(uint32_t))) return 0;
572 p
= kv
->databuf
+ kv
->_dict
;
574 memcpy(&x
, p
, sizeof(uint32_t));
580 p
= kv
->databuf
+ kv
->_dict
;
583 memcpy(&x
, p
, sizeof(uint32_t));
584 p
+= sizeof(uint32_t);
585 kv
->_dict
+= sizeof(uint32_t);
588 for (k
= 0; k
< kcount
; k
++)
591 memcpy(&x
, p
, sizeof(uint32_t));
592 p
+= sizeof(uint32_t);
593 kv
->_dict
+= sizeof(uint32_t);
599 memcpy(&x
, p
, sizeof(uint32_t));
600 p
+= sizeof(uint32_t);
601 kv
->_dict
+= sizeof(uint32_t);
604 for (v
= 0; v
< vcount
; v
++)
607 memcpy(&x
, p
, sizeof(uint32_t));
608 p
+= sizeof(uint32_t);
609 kv
->_dict
+= sizeof(uint32_t);
616 if (kv
->datalen
< (kv
->_dict
+ sizeof(uint32_t))) return 0;
618 p
= kv
->databuf
+ kv
->_dict
;
620 memcpy(&x
, p
, sizeof(uint32_t));
626 /* advance to next key, returns key and sets val_count */
628 kvbuf_next_key(kvbuf_t
*kv
, uint32_t *val_count
)
630 uint32_t x
, kl
, v
, vl
, vc
;
633 if (kv
== NULL
) return NULL
;
634 if (val_count
== NULL
) return NULL
;
638 if (kv
->databuf
== NULL
) return NULL
;
639 if (kv
->_dict
== 0) return NULL
;
647 if (kv
->datalen
< (kv
->_dict
+ sizeof(uint32_t))) return NULL
;
648 kv
->_key
= kv
->_dict
+ sizeof(uint32_t);
652 p
= kv
->databuf
+ kv
->_key
;
655 memcpy(&x
, p
, sizeof(uint32_t));
658 if (kv
->datalen
< (kv
->_key
+ sizeof(uint32_t) + kl
)) return NULL
;
660 p
+= (sizeof(uint32_t) + kl
);
661 kv
->_key
+= (sizeof(uint32_t) + kl
);
663 /* skip over values */
664 if (kv
->datalen
< (kv
->_key
+ sizeof(uint32_t))) return NULL
;
667 memcpy(&x
, p
, sizeof(uint32_t));
670 p
+= sizeof(uint32_t);
671 kv
->_key
+= sizeof(uint32_t);
673 for (v
= 0; v
< vc
; v
++)
675 if (kv
->datalen
< (kv
->_key
+ sizeof(uint32_t))) return NULL
;
678 memcpy(&x
, p
, sizeof(uint32_t));
681 if (kv
->datalen
< (kv
->_key
+ kl
)) return NULL
;
683 p
+= (sizeof(uint32_t) + vl
);
684 kv
->_key
+= (sizeof(uint32_t) + vl
);
688 if (kv
->datalen
< (kv
->_key
+ sizeof(uint32_t))) return NULL
;
690 p
= kv
->databuf
+ kv
->_key
;
692 memcpy(&x
, p
, sizeof(uint32_t));
695 p
+= sizeof(uint32_t);
698 kv
->_vlist
= kv
->_key
+ sizeof(uint32_t) + kl
;
699 if (kv
->datalen
< (kv
->_vlist
+ sizeof(uint32_t)))
705 p
= kv
->databuf
+ kv
->_vlist
;
707 memcpy(&x
, p
, sizeof(uint32_t));
708 *val_count
= ntohl(x
);
714 kvbuf_next_val(kvbuf_t
*kv
)
716 return kvbuf_next_val_len(kv
, NULL
);
720 kvbuf_next_val_len(kvbuf_t
*kv
, uint32_t *len
)
726 if (kv
== NULL
) return NULL
;
727 if (kv
->databuf
== NULL
) return NULL
;
728 if (kv
->_vlist
== 0) return NULL
;
733 if (kv
->datalen
< (kv
->_vlist
+ sizeof(uint32_t))) return NULL
;
734 kv
->_val
= kv
->_vlist
+ sizeof(uint32_t);
736 p
= kv
->databuf
+ kv
->_val
;
738 memcpy(&x
, p
, sizeof(uint32_t));
743 p
= kv
->databuf
+ kv
->_val
;
745 memcpy(&x
, p
, sizeof(uint32_t));
748 if (kv
->datalen
< (kv
->_val
+ sizeof(uint32_t) + vltemp
)) return NULL
;
750 p
+= (sizeof(uint32_t) + vltemp
);
751 kv
->_val
+= (sizeof(uint32_t) + vltemp
);
754 if (kv
->datalen
< (kv
->_val
+ sizeof(uint32_t))) return NULL
;
756 if (len
!= NULL
) (*len
) = vltemp
;
757 p
= kv
->databuf
+ kv
->_val
+ sizeof(uint32_t);
762 * Builds a kvarray_t / kvdict_t structure on top of a kvbuf_t.
763 * It allocates the appropriate number of kvdict_t structures
764 * for the array, sets all the counters, and fills in pointers
765 * for keys and valuse. The pointers are NOT to newly allocated
766 * strings: they just point into the kvbuf data buffer.
768 * To dispose of the kvarray_t and all of the associated
769 * memory AND to free the original kvbuf, clients only
770 * need to call kvarray_free().
773 kvbuf_decode(kvbuf_t
*kv
)
779 if (kv
== NULL
) return NULL
;
780 if (kv
->databuf
== NULL
) return NULL
;
782 if (kv
->datalen
< sizeof(uint32_t)) return NULL
;
785 kv
->_size
= kv
->datalen
;
789 memcpy(&x
, p
, sizeof(uint32_t));
790 p
+= sizeof(uint32_t);
791 kv
->_size
-= sizeof(uint32_t);
794 if (x
== 0) return NULL
;
796 a
= (kvarray_t
*)calloc(1, sizeof(kvarray_t
));
797 if (a
== NULL
) return NULL
;
800 a
->dict
= (kvdict_t
*)calloc(a
->count
, sizeof(kvdict_t
));
807 for (d
= 0; d
< a
->count
; d
++)
809 if (kv
->_size
< sizeof(uint32_t))
817 memcpy(&x
, p
, sizeof(uint32_t));
818 p
+= sizeof(uint32_t);
819 kv
->_size
-= sizeof(uint32_t);
820 a
->dict
[d
].kcount
= ntohl(x
);
822 if (a
->dict
[d
].kcount
> 0)
824 a
->dict
[d
].key
= (const char **)calloc(a
->dict
[d
].kcount
, sizeof(const char *));
825 if (a
->dict
[d
].key
== NULL
)
831 a
->dict
[d
].vcount
= (uint32_t *)calloc(a
->dict
[d
].kcount
, sizeof(uint32_t));
832 if (a
->dict
[d
].vcount
== NULL
)
838 a
->dict
[d
].val
= (const char ***)calloc(a
->dict
[d
].kcount
, sizeof(char **));
839 if (a
->dict
[d
].val
== NULL
)
846 for (k
= 0; k
< a
->dict
[d
].kcount
; k
++)
849 if (kv
->_size
< sizeof(uint32_t))
857 memcpy(&x
, p
, sizeof(uint32_t));
858 p
+= sizeof(uint32_t);
859 kv
->_size
-= sizeof(uint32_t);
869 a
->dict
[d
].key
[k
] = p
;
874 if (kv
->_size
< sizeof(uint32_t))
882 memcpy(&x
, p
, sizeof(uint32_t));
883 p
+= sizeof(uint32_t);
884 kv
->_size
-= sizeof(uint32_t);
885 a
->dict
[d
].vcount
[k
] = ntohl(x
);
887 if (a
->dict
[d
].vcount
[k
] > 0)
889 /* N.B. we add a NULL pointer at the end of the list */
890 a
->dict
[d
].val
[k
] = (const char **)calloc(a
->dict
[d
].vcount
[k
] + 1, sizeof(const char *));
891 if (a
->dict
[d
].val
[k
] == NULL
)
898 for (v
= 0; v
< a
->dict
[d
].vcount
[k
]; v
++)
901 if (kv
->_size
< sizeof(uint32_t))
909 memcpy(&x
, p
, sizeof(uint32_t));
910 p
+= sizeof(uint32_t);
911 kv
->_size
-= sizeof(uint32_t);
921 a
->dict
[d
].val
[k
][v
] = p
;
934 kvarray_free(kvarray_t
*a
)
938 if (a
== NULL
) return;
940 for (d
= 0; d
< a
->count
; d
++)
942 for (k
= 0; k
< a
->dict
[d
].kcount
; k
++)
944 if (a
->dict
[d
].val
== NULL
) continue;
945 if (a
->dict
[d
].val
[k
] != NULL
) free(a
->dict
[d
].val
[k
]);
948 if (a
->dict
[d
].key
!= NULL
) free(a
->dict
[d
].key
);
949 if (a
->dict
[d
].vcount
!= NULL
) free(a
->dict
[d
].vcount
);
950 if (a
->dict
[d
].val
!= NULL
) free(a
->dict
[d
].val
);
955 if (a
->dict
!= NULL
) free(a
->dict
);
958 if (a
->kv
!= NULL
) kvbuf_free(a
->kv
);