-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor argv_array into generic code
The submodule code recently grew generic code to build a dynamic argv array. Many other parts of the code can reuse this, too, so let's make it generically available. There are two enhancements not found in the original code: 1. We now handle the NULL-termination invariant properly, even when no strings have been pushed (before, you could have an empty, NULL argv). This was not a problem for the submodule code, which always pushed at least one argument, but was not sufficiently safe for generic code. 2. There is a formatted variant of the "push" function. This is a convenience function which was not needed by the submodule code, but will make it easier to port other users to the new code. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
- Loading branch information
Jeff King
authored and
Junio C Hamano
committed
Sep 14, 2011
1 parent
7878b07
commit c1189ca
Showing
5 changed files
with
125 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters