Browse Source
* jk/argv-array: run_hook: use argv_array API checkout: use argv_array API bisect: use argv_array API quote: provide sq_dequote_to_argv_array refactor argv_array into generic code quote.h: fix bogus comment add sha1_array API docsmaint

11 changed files with 261 additions and 107 deletions
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
argv-array API |
||||
============== |
||||
|
||||
The argv-array API allows one to dynamically build and store |
||||
NULL-terminated lists. An argv-array maintains the invariant that the |
||||
`argv` member always points to a non-NULL array, and that the array is |
||||
always NULL-terminated at the element pointed to by `argv[argc]`. This |
||||
makes the result suitable for passing to functions expecting to receive |
||||
argv from main(), or the link:api-run-command.html[run-command API]. |
||||
|
||||
The link:api-string-list.html[string-list API] is similar, but cannot be |
||||
used for these purposes; instead of storing a straight string pointer, |
||||
it contains an item structure with a `util` field that is not compatible |
||||
with the traditional argv interface. |
||||
|
||||
Each `argv_array` manages its own memory. Any strings pushed into the |
||||
array are duplicated, and all memory is freed by argv_array_clear(). |
||||
|
||||
Data Structures |
||||
--------------- |
||||
|
||||
`struct argv_array`:: |
||||
|
||||
A single array. This should be initialized by assignment from |
||||
`ARGV_ARRAY_INIT`, or by calling `argv_array_init`. The `argv` |
||||
member contains the actual array; the `argc` member contains the |
||||
number of elements in the array, not including the terminating |
||||
NULL. |
||||
|
||||
Functions |
||||
--------- |
||||
|
||||
`argv_array_init`:: |
||||
Initialize an array. This is no different than assigning from |
||||
`ARGV_ARRAY_INIT`. |
||||
|
||||
`argv_array_push`:: |
||||
Push a copy of a string onto the end of the array. |
||||
|
||||
`argv_array_pushf`:: |
||||
Format a string and push it onto the end of the array. This is a |
||||
convenience wrapper combining `strbuf_addf` and `argv_array_push`. |
||||
|
||||
`argv_array_clear`:: |
||||
Free all memory associated with the array and return it to the |
||||
initial, empty state. |
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
sha1-array API |
||||
============== |
||||
|
||||
The sha1-array API provides storage and manipulation of sets of SHA1 |
||||
identifiers. The emphasis is on storage and processing efficiency, |
||||
making them suitable for large lists. Note that the ordering of items is |
||||
not preserved over some operations. |
||||
|
||||
Data Structures |
||||
--------------- |
||||
|
||||
`struct sha1_array`:: |
||||
|
||||
A single array of SHA1 hashes. This should be initialized by |
||||
assignment from `SHA1_ARRAY_INIT`. The `sha1` member contains |
||||
the actual data. The `nr` member contains the number of items in |
||||
the set. The `alloc` and `sorted` members are used internally, |
||||
and should not be needed by API callers. |
||||
|
||||
Functions |
||||
--------- |
||||
|
||||
`sha1_array_append`:: |
||||
Add an item to the set. The sha1 will be placed at the end of |
||||
the array (but note that some operations below may lose this |
||||
ordering). |
||||
|
||||
`sha1_array_sort`:: |
||||
Sort the elements in the array. |
||||
|
||||
`sha1_array_lookup`:: |
||||
Perform a binary search of the array for a specific sha1. |
||||
If found, returns the offset (in number of elements) of the |
||||
sha1. If not found, returns a negative integer. If the array is |
||||
not sorted, this function has the side effect of sorting it. |
||||
|
||||
`sha1_array_clear`:: |
||||
Free all memory associated with the array and return it to the |
||||
initial, empty state. |
||||
|
||||
`sha1_array_for_each_unique`:: |
||||
Efficiently iterate over each unique element of the list, |
||||
executing the callback function for each one. If the array is |
||||
not sorted, this function has the side effect of sorting it. |
||||
|
||||
Examples |
||||
-------- |
||||
|
||||
----------------------------------------- |
||||
void print_callback(const unsigned char sha1[20], |
||||
void *data) |
||||
{ |
||||
printf("%s\n", sha1_to_hex(sha1)); |
||||
} |
||||
|
||||
void some_func(void) |
||||
{ |
||||
struct sha1_array hashes = SHA1_ARRAY_INIT; |
||||
unsigned char sha1[20]; |
||||
|
||||
/* Read objects into our set */ |
||||
while (read_object_from_stdin(sha1)) |
||||
sha1_array_append(&hashes, sha1); |
||||
|
||||
/* Check if some objects are in our set */ |
||||
while (read_object_from_stdin(sha1)) { |
||||
if (sha1_array_lookup(&hashes, sha1) >= 0) |
||||
printf("it's in there!\n"); |
||||
|
||||
/* |
||||
* Print the unique set of objects. We could also have |
||||
* avoided adding duplicate objects in the first place, |
||||
* but we would end up re-sorting the array repeatedly. |
||||
* Instead, this will sort once and then skip duplicates |
||||
* in linear time. |
||||
*/ |
||||
sha1_array_for_each_unique(&hashes, print_callback, NULL); |
||||
} |
||||
----------------------------------------- |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
#include "cache.h" |
||||
#include "argv-array.h" |
||||
#include "strbuf.h" |
||||
|
||||
static const char *empty_argv_storage = NULL; |
||||
const char **empty_argv = &empty_argv_storage; |
||||
|
||||
void argv_array_init(struct argv_array *array) |
||||
{ |
||||
array->argv = empty_argv; |
||||
array->argc = 0; |
||||
array->alloc = 0; |
||||
} |
||||
|
||||
static void argv_array_push_nodup(struct argv_array *array, const char *value) |
||||
{ |
||||
if (array->argv == empty_argv) |
||||
array->argv = NULL; |
||||
|
||||
ALLOC_GROW(array->argv, array->argc + 2, array->alloc); |
||||
array->argv[array->argc++] = value; |
||||
array->argv[array->argc] = NULL; |
||||
} |
||||
|
||||
void argv_array_push(struct argv_array *array, const char *value) |
||||
{ |
||||
argv_array_push_nodup(array, xstrdup(value)); |
||||
} |
||||
|
||||
void argv_array_pushf(struct argv_array *array, const char *fmt, ...) |
||||
{ |
||||
va_list ap; |
||||
struct strbuf v = STRBUF_INIT; |
||||
|
||||
va_start(ap, fmt); |
||||
strbuf_vaddf(&v, fmt, ap); |
||||
va_end(ap); |
||||
|
||||
argv_array_push_nodup(array, strbuf_detach(&v, NULL)); |
||||
} |
||||
|
||||
void argv_array_clear(struct argv_array *array) |
||||
{ |
||||
if (array->argv != empty_argv) { |
||||
int i; |
||||
for (i = 0; i < array->argc; i++) |
||||
free((char **)array->argv[i]); |
||||
free(array->argv); |
||||
} |
||||
argv_array_init(array); |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
#ifndef ARGV_ARRAY_H |
||||
#define ARGV_ARRAY_H |
||||
|
||||
extern const char **empty_argv; |
||||
|
||||
struct argv_array { |
||||
const char **argv; |
||||
int argc; |
||||
int alloc; |
||||
}; |
||||
|
||||
#define ARGV_ARRAY_INIT { empty_argv, 0, 0 } |
||||
|
||||
void argv_array_init(struct argv_array *); |
||||
void argv_array_push(struct argv_array *, const char *); |
||||
__attribute__((format (printf,2,3))) |
||||
void argv_array_pushf(struct argv_array *, const char *fmt, ...); |
||||
void argv_array_clear(struct argv_array *); |
||||
|
||||
#endif /* ARGV_ARRAY_H */ |
Loading…
Reference in new issue