Show Contents Previous Page Next Page
Chapter 10 - C API Reference Guide, Part I The Array API In this section... Introduction Show Contents Go to Top Previous Page Next Page The HTTP protocol is filled with lists: lists of language
codes, HTTP header fields, MIME types, and so forth.
In general, it's not possible to predict the size of
the lists in advance, and some of them can be quite
large. In order to deal with this, Apache provides an
array API that allows you to create lists of arbitrary
type and length, much like the dynamic arrays provided
by Perl. More complex data structures, such as the table
type (described later in this chapter), are built on
top of Apache arrays. The array_header Type Show Contents Go to Top Previous Page Next Page The core of the array API is the array_header
structure, whose definition you can find in include/alloc.h:
typedef struct {
ap_pool *pool;
int elt_size;
int nelts;
int nalloc;
char *elts;
} array_header;
The fields you'll use are the nelts field,
which holds the current number of elements in the array,
and the elts field, which contains a pointer
to the data in the array. elts is declared
as a char* for the convenience of internal
routines. You will need to cast it to a pointer of the
correct type before you can access elements safely.
You should not need to worry about the other fields,
but note that the array_header contains
a pointer back to the resource pool from which it was
allocated. This means that both the array header and
its contents will be freed automatically when the pool
reaches the end of its lifetime. Creating and Manipulating Arrays Show Contents Go to Top Previous Page Next Page Here are the API calls for working with arrays. Although
array elements can be of any arbitrary type, we use
char* strings in our examples for the sake
of simplicity. array_header *ap_make_array (pool* p, int nelts, int elt_size)
This function allocates a new array from resource
pool p with elements elt_size bytes
in length and enough initial space to hold nelts
elements. If successful, the call will return a pointer
to a new array_header . If the array needs to grow beyond its initial length,
the array API will resize it automatically. This means
that you can safely allocate an array with zero elements.
Here is an example of creating a new array with an
initial length of 5 elements. Each element is large enough
to hold a char* string pointer:
array_header *arr = ap_make_array(p, 5, sizeof(char*));
void *ap_push_array (array_header *arr)
The ap_push_array() function is used to add
a new element to the end of the list. It works a little
differently than you would expect. Instead of allocating
the new element first and then pushing it onto the end
of the list, you call ap_push_array() to allocate
the element for you. It will create a new element of the
correct size within the array's pool and return a pointer
to the new element. You cast the returned void*
to the data type of your choice and copy your data in.
Here's an example in which we add a new element containing
the string text/html to the end of the array. The
call to ap_push_array() allocates room for a new
char* pointer, while the subsequent call to
ap_pstrdup() allocates room for the string itself
and copies its address into the element. This example assumes
that the array was created with ap_ make_array()
using an elt_size determined by sizeof(char
*) .
char **new;
new = (char **)ap_push_array(arr);
*new = ap_pstrdup(r->pool, "text/html");
/* or in a single line */
*(char **)ap_push_array(arr) = ap_pstrdup(r->pool, "text/html");
void ap_array_cat (array_header *dst, const array_header *src)
If you wish to add the elements of one array to another,
the ap_array_cat() function will handle the job.
It takes two array_header pointers as arguments
and concatenates the second onto the end of the first. The
first will grow as necessary. Note that the elt_size
used to create each array should be the same; otherwise,
unpredictable results may occur.
ap_array_cat(arr, other_arr);
array_header *ap_append_arrays (pool *p, const array_header *a1, const
array_header *a2)
This function is similar to ap_array_cat() but
creates a brand new array in the indicated pool. The resulting
array will be the concatenation of a1 and a2.
array_header *new = ap_append_arrays(p, one_array, another_array);
char *ap_array_pstrcat (pool *p, const array_header *arr, const char
sep)
This function builds a new string using the elements
of the given array. If sep is non- NULL ,
it will be inserted as a delimiter between the substrings.
char *table_cells = ap_array_pstrcat(r->pool, cells, ' ');
array_header *ap_copy_array (pool *p, const array_header *src)
The ap_copy_array() function creates a new array
in the indicated pool, then copies into it all the elements
in src.
array_header *new = ap_copy_array(p, arr);
array_header *ap_copy_array_hdr (pool *p, const array_header *src)
This function is similar to ap_copy_array()
but implements a deferred copy. Initially only a new header
is created which points back to the data of the original
array. Only if the new copy is extended with an ap_push_array()
or ap_array_cat() is the old data copied. If the
array is never extended, it avoids the overhead of a full
copy.
array_header *new = ap_copy_array_hdr(p, arr);
Accessing Array Elements Show Contents Go to Top Previous Page Next Page There are no functions in the API to fetch specific elements
or to iterate over the list. However, it is simple enough
to pull the array out of the elts field and typecast
it into a C array of the proper type. You can use the nelts
field to keep track of the number of elements inside the array.
In this example, we iterate over the entire array, printing
out its contents (using the ap_rprintf() function,
which we will discuss later):
char **list = (char**)arr->elts;
for(i = 0; i < arr->nelts; i++) {
ap_rprintf(r, "item %d -> %s\n", i, list[i]);
}
Changing an item in the array is done in a similar way:
((char **)arr->elts)[2] = "transmission aborted"
If you wish to clear the array, simply set nelts
to zero:
arr->nelts = 0;
Show Contents Go to Top Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |