1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter#ifndef APR_TABLES_H 18251875Speter#define APR_TABLES_H 19251875Speter 20251875Speter/** 21251875Speter * @file apr_tables.h 22251875Speter * @brief APR Table library 23251875Speter */ 24251875Speter 25251875Speter#include "apr.h" 26251875Speter#include "apr_pools.h" 27251875Speter 28251875Speter#if APR_HAVE_STDARG_H 29251875Speter#include <stdarg.h> /* for va_list */ 30251875Speter#endif 31251875Speter 32251875Speter#ifdef __cplusplus 33251875Speterextern "C" { 34251875Speter#endif /* __cplusplus */ 35251875Speter 36251875Speter/** 37251875Speter * @defgroup apr_tables Table and Array Functions 38251875Speter * @ingroup APR 39251875Speter * Arrays are used to store data which is referenced sequentially or 40251875Speter * as a stack. Functions are provided to push and pop individual 41251875Speter * elements as well as to operate on the entire array. 42251875Speter * 43251875Speter * Tables are used to store data which can be referenced by key. 44251875Speter * Limited capabilities are provided for tables with multiple elements 45251875Speter * which share a key; while key lookup will return only a single 46251875Speter * element, iteration is available. Additionally, a table can be 47251875Speter * compressed to resolve duplicates. 48251875Speter * 49251875Speter * Both arrays and tables may store string or binary data; some features, 50251875Speter * such as concatenation or merging of elements, work only for string 51251875Speter * data. 52251875Speter * @{ 53251875Speter */ 54251875Speter 55251875Speter/** the table abstract data type */ 56251875Spetertypedef struct apr_table_t apr_table_t; 57251875Speter 58251875Speter/** @see apr_array_header_t */ 59251875Spetertypedef struct apr_array_header_t apr_array_header_t; 60251875Speter 61251875Speter/** An opaque array type */ 62251875Speterstruct apr_array_header_t { 63251875Speter /** The pool the array is allocated out of */ 64251875Speter apr_pool_t *pool; 65251875Speter /** The amount of memory allocated for each element of the array */ 66251875Speter int elt_size; 67251875Speter /** The number of active elements in the array */ 68251875Speter int nelts; 69251875Speter /** The number of elements allocated in the array */ 70251875Speter int nalloc; 71251875Speter /** The elements in the array */ 72251875Speter char *elts; 73251875Speter}; 74251875Speter 75251875Speter/** 76251875Speter * The (opaque) structure for string-content tables. 77251875Speter */ 78251875Spetertypedef struct apr_table_entry_t apr_table_entry_t; 79251875Speter 80251875Speter/** The type for each entry in a string-content table */ 81251875Speterstruct apr_table_entry_t { 82251875Speter /** The key for the current table entry */ 83251875Speter char *key; /* maybe NULL in future; 84251875Speter * check when iterating thru table_elts 85251875Speter */ 86251875Speter /** The value for the current table entry */ 87251875Speter char *val; 88251875Speter 89251875Speter /** A checksum for the key, for use by the apr_table internals */ 90251875Speter apr_uint32_t key_checksum; 91251875Speter}; 92251875Speter 93251875Speter/** 94251875Speter * Get the elements from a table. 95251875Speter * @param t The table 96251875Speter * @return An array containing the contents of the table 97251875Speter */ 98251875SpeterAPR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t); 99251875Speter 100251875Speter/** 101251875Speter * Determine if the table is empty (either NULL or having no elements). 102251875Speter * @param t The table to check 103251875Speter * @return True if empty, False otherwise 104251875Speter */ 105251875SpeterAPR_DECLARE(int) apr_is_empty_table(const apr_table_t *t); 106251875Speter 107251875Speter/** 108251875Speter * Determine if the array is empty (either NULL or having no elements). 109251875Speter * @param a The array to check 110251875Speter * @return True if empty, False otherwise 111251875Speter */ 112251875SpeterAPR_DECLARE(int) apr_is_empty_array(const apr_array_header_t *a); 113251875Speter 114251875Speter/** 115251875Speter * Create an array. 116251875Speter * @param p The pool to allocate the memory out of 117251875Speter * @param nelts the number of elements in the initial array 118251875Speter * @param elt_size The size of each element in the array. 119251875Speter * @return The new array 120251875Speter */ 121251875SpeterAPR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p, 122251875Speter int nelts, int elt_size); 123251875Speter 124251875Speter/** 125251875Speter * Add a new element to an array (as a first-in, last-out stack). 126251875Speter * @param arr The array to add an element to. 127251875Speter * @return Location for the new element in the array. 128251875Speter * @remark If there are no free spots in the array, then this function will 129251875Speter * allocate new space for the new element. 130251875Speter */ 131251875SpeterAPR_DECLARE(void *) apr_array_push(apr_array_header_t *arr); 132251875Speter 133251875Speter/** A helper macro for accessing a member of an APR array. 134251875Speter * 135251875Speter * @param ary the array 136251875Speter * @param i the index into the array to return 137251875Speter * @param type the type of the objects stored in the array 138251875Speter * 139251875Speter * @return the item at index i 140251875Speter */ 141251875Speter#define APR_ARRAY_IDX(ary,i,type) (((type *)(ary)->elts)[i]) 142251875Speter 143251875Speter/** A helper macro for pushing elements into an APR array. 144251875Speter * 145251875Speter * @param ary the array 146251875Speter * @param type the type of the objects stored in the array 147251875Speter * 148251875Speter * @return the location where the new object should be placed 149251875Speter */ 150251875Speter#define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary))) 151251875Speter 152251875Speter/** 153251875Speter * Remove an element from an array (as a first-in, last-out stack). 154251875Speter * @param arr The array to remove an element from. 155251875Speter * @return Location of the element in the array. 156251875Speter * @remark If there are no elements in the array, NULL is returned. 157251875Speter */ 158251875SpeterAPR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr); 159251875Speter 160251875Speter/** 161251875Speter * Remove all elements from an array. 162251875Speter * @param arr The array to remove all elements from. 163251875Speter * @remark As the underlying storage is allocated from a pool, no 164251875Speter * memory is freed by this operation, but is available for reuse. 165251875Speter */ 166251875SpeterAPR_DECLARE(void) apr_array_clear(apr_array_header_t *arr); 167251875Speter 168251875Speter/** 169251875Speter * Concatenate two arrays together. 170251875Speter * @param dst The destination array, and the one to go first in the combined 171251875Speter * array 172251875Speter * @param src The source array to add to the destination array 173251875Speter */ 174251875SpeterAPR_DECLARE(void) apr_array_cat(apr_array_header_t *dst, 175251875Speter const apr_array_header_t *src); 176251875Speter 177251875Speter/** 178251875Speter * Copy the entire array. 179251875Speter * @param p The pool to allocate the copy of the array out of 180251875Speter * @param arr The array to copy 181251875Speter * @return An exact copy of the array passed in 182362181Sdim * @remark The alternate apr_array_copy_hdr() copies only the header, and arranges 183251875Speter * for the elements to be copied if (and only if) the code subsequently 184251875Speter * does a push or arraycat. 185251875Speter */ 186251875SpeterAPR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p, 187251875Speter const apr_array_header_t *arr); 188251875Speter/** 189251875Speter * Copy the headers of the array, and arrange for the elements to be copied if 190251875Speter * and only if the code subsequently does a push or arraycat. 191251875Speter * @param p The pool to allocate the copy of the array out of 192251875Speter * @param arr The array to copy 193251875Speter * @return An exact copy of the array passed in 194362181Sdim * @remark The alternate apr_array_copy() copies the *entire* array. 195251875Speter */ 196251875SpeterAPR_DECLARE(apr_array_header_t *) apr_array_copy_hdr(apr_pool_t *p, 197251875Speter const apr_array_header_t *arr); 198251875Speter 199251875Speter/** 200251875Speter * Append one array to the end of another, creating a new array in the process. 201251875Speter * @param p The pool to allocate the new array out of 202251875Speter * @param first The array to put first in the new array. 203251875Speter * @param second The array to put second in the new array. 204251875Speter * @return A new array containing the data from the two arrays passed in. 205251875Speter*/ 206251875SpeterAPR_DECLARE(apr_array_header_t *) apr_array_append(apr_pool_t *p, 207251875Speter const apr_array_header_t *first, 208251875Speter const apr_array_header_t *second); 209251875Speter 210251875Speter/** 211251875Speter * Generate a new string from the apr_pool_t containing the concatenated 212251875Speter * sequence of substrings referenced as elements within the array. The string 213251875Speter * will be empty if all substrings are empty or null, or if there are no 214251875Speter * elements in the array. If sep is non-NUL, it will be inserted between 215251875Speter * elements as a separator. 216251875Speter * @param p The pool to allocate the string out of 217251875Speter * @param arr The array to generate the string from 218251875Speter * @param sep The separator to use 219251875Speter * @return A string containing all of the data in the array. 220251875Speter */ 221251875SpeterAPR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p, 222251875Speter const apr_array_header_t *arr, 223251875Speter const char sep); 224251875Speter 225251875Speter/** 226251875Speter * Make a new table. 227251875Speter * @param p The pool to allocate the pool out of 228251875Speter * @param nelts The number of elements in the initial table. 229251875Speter * @return The new table. 230251875Speter * @warning This table can only store text data 231251875Speter */ 232251875SpeterAPR_DECLARE(apr_table_t *) apr_table_make(apr_pool_t *p, int nelts); 233251875Speter 234251875Speter/** 235251875Speter * Create a new table and copy another table into it. 236251875Speter * @param p The pool to allocate the new table out of 237251875Speter * @param t The table to copy 238251875Speter * @return A copy of the table passed in 239251875Speter * @warning The table keys and respective values are not copied 240251875Speter */ 241251875SpeterAPR_DECLARE(apr_table_t *) apr_table_copy(apr_pool_t *p, 242251875Speter const apr_table_t *t); 243251875Speter 244251875Speter/** 245251875Speter * Create a new table whose contents are deep copied from the given 246251875Speter * table. A deep copy operation copies all fields, and makes copies 247251875Speter * of dynamically allocated memory pointed to by the fields. 248251875Speter * @param p The pool to allocate the new table out of 249251875Speter * @param t The table to clone 250251875Speter * @return A deep copy of the table passed in 251251875Speter */ 252251875SpeterAPR_DECLARE(apr_table_t *) apr_table_clone(apr_pool_t *p, 253251875Speter const apr_table_t *t); 254251875Speter 255251875Speter/** 256251875Speter * Delete all of the elements from a table. 257251875Speter * @param t The table to clear 258251875Speter */ 259251875SpeterAPR_DECLARE(void) apr_table_clear(apr_table_t *t); 260251875Speter 261251875Speter/** 262251875Speter * Get the value associated with a given key from the table. After this call, 263251875Speter * the data is still in the table. 264251875Speter * @param t The table to search for the key 265251875Speter * @param key The key to search for (case does not matter) 266251875Speter * @return The value associated with the key, or NULL if the key does not exist. 267251875Speter */ 268251875SpeterAPR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key); 269251875Speter 270251875Speter/** 271266735Speter * Get values associated with a given key from the table. If more than one 272266735Speter * value exists, return a comma separated list of values. After this call, the 273266735Speter * data is still in the table. 274266735Speter * @param p The pool to allocate the combined value from, if necessary 275266735Speter * @param t The table to search for the key 276266735Speter * @param key The key to search for (case does not matter) 277266735Speter * @return The value associated with the key, or NULL if the key does not exist. 278266735Speter */ 279266735SpeterAPR_DECLARE(const char *) apr_table_getm(apr_pool_t *p, const apr_table_t *t, 280266735Speter const char *key); 281266735Speter 282266735Speter/** 283251875Speter * Add a key/value pair to a table. If another element already exists with the 284251875Speter * same key, this will overwrite the old data. 285251875Speter * @param t The table to add the data to. 286251875Speter * @param key The key to use (case does not matter) 287251875Speter * @param val The value to add 288251875Speter * @remark When adding data, this function makes a copy of both the key and the 289251875Speter * value. 290251875Speter */ 291251875SpeterAPR_DECLARE(void) apr_table_set(apr_table_t *t, const char *key, 292251875Speter const char *val); 293251875Speter 294251875Speter/** 295251875Speter * Add a key/value pair to a table. If another element already exists with the 296251875Speter * same key, this will overwrite the old data. 297251875Speter * @param t The table to add the data to. 298251875Speter * @param key The key to use (case does not matter) 299251875Speter * @param val The value to add 300251875Speter * @warning When adding data, this function does not make a copy of the key or 301251875Speter * the value, so care should be taken to ensure that the values will 302251875Speter * not change after they have been added.. 303251875Speter */ 304251875SpeterAPR_DECLARE(void) apr_table_setn(apr_table_t *t, const char *key, 305251875Speter const char *val); 306251875Speter 307251875Speter/** 308251875Speter * Remove data from the table. 309251875Speter * @param t The table to remove data from 310251875Speter * @param key The key of the data being removed (case does not matter) 311251875Speter */ 312251875SpeterAPR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key); 313251875Speter 314251875Speter/** 315251875Speter * Add data to a table by merging the value with data that has already been 316251875Speter * stored. The merging is done by concatenating the two values, separated 317251875Speter * by the string ", ". 318251875Speter * @param t The table to search for the data 319251875Speter * @param key The key to merge data for (case does not matter) 320251875Speter * @param val The data to add 321362181Sdim * @remark If the key is not found, then this function acts like apr_table_add() 322251875Speter */ 323251875SpeterAPR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key, 324251875Speter const char *val); 325251875Speter 326251875Speter/** 327251875Speter * Add data to a table by merging the value with data that has already been 328251875Speter * stored. The merging is done by concatenating the two values, separated 329251875Speter * by the string ", ". 330251875Speter * @param t The table to search for the data 331251875Speter * @param key The key to merge data for (case does not matter) 332251875Speter * @param val The data to add 333362181Sdim * @remark If the key is not found, then this function acts like apr_table_addn() 334251875Speter */ 335251875SpeterAPR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key, 336251875Speter const char *val); 337251875Speter 338251875Speter/** 339251875Speter * Add data to a table, regardless of whether there is another element with the 340251875Speter * same key. 341251875Speter * @param t The table to add to 342251875Speter * @param key The key to use 343251875Speter * @param val The value to add. 344251875Speter * @remark When adding data, this function makes a copy of both the key and the 345251875Speter * value. 346251875Speter */ 347251875SpeterAPR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key, 348251875Speter const char *val); 349251875Speter 350251875Speter/** 351251875Speter * Add data to a table, regardless of whether there is another element with the 352251875Speter * same key. 353251875Speter * @param t The table to add to 354251875Speter * @param key The key to use 355251875Speter * @param val The value to add. 356251875Speter * @remark When adding data, this function does not make a copy of the key or the 357251875Speter * value, so care should be taken to ensure that the values will not 358251875Speter * change after they have been added. 359251875Speter */ 360251875SpeterAPR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key, 361251875Speter const char *val); 362251875Speter 363251875Speter/** 364251875Speter * Merge two tables into one new table. 365251875Speter * @param p The pool to use for the new table 366251875Speter * @param overlay The first table to put in the new table 367251875Speter * @param base The table to add at the end of the new table 368251875Speter * @return A new table containing all of the data from the two passed in 369251875Speter */ 370251875SpeterAPR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p, 371251875Speter const apr_table_t *overlay, 372251875Speter const apr_table_t *base); 373251875Speter 374251875Speter/** 375251875Speter * Declaration prototype for the iterator callback function of apr_table_do() 376251875Speter * and apr_table_vdo(). 377251875Speter * @param rec The data passed as the first argument to apr_table_[v]do() 378251875Speter * @param key The key from this iteration of the table 379251875Speter * @param value The value from this iteration of the table 380251875Speter * @remark Iteration continues while this callback function returns non-zero. 381251875Speter * To export the callback function for apr_table_[v]do() it must be declared 382251875Speter * in the _NONSTD convention. 383362181Sdim * @see apr_table_do @see apr_table_vdo 384251875Speter */ 385251875Spetertypedef int (apr_table_do_callback_fn_t)(void *rec, const char *key, 386251875Speter const char *value); 387251875Speter 388251875Speter/** 389251875Speter * Iterate over a table running the provided function once for every 390251875Speter * element in the table. The varargs array must be a list of zero or 391251875Speter * more (char *) keys followed by a NULL pointer. If zero keys are 392251875Speter * given, the @param comp function will be invoked for every element 393251875Speter * in the table. Otherwise, the function is invoked only for those 394251875Speter * elements matching the keys specified. 395251875Speter * 396362181Sdim * If an invocation of the comp function returns zero, 397251875Speter * iteration will continue using the next specified key, if any. 398251875Speter * 399251875Speter * @param comp The function to run 400251875Speter * @param rec The data to pass as the first argument to the function 401251875Speter * @param t The table to iterate over 402251875Speter * @param ... A varargs array of zero or more (char *) keys followed by NULL 403251875Speter * @return FALSE if one of the comp() iterations returned zero; TRUE if all 404251875Speter * iterations returned non-zero 405362181Sdim * @see apr_table_do_callback_fn_t @see apr_table_vdo 406251875Speter */ 407251875SpeterAPR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp, 408251875Speter void *rec, const apr_table_t *t, ...) 409251875Speter#if defined(__GNUC__) && __GNUC__ >= 4 410251875Speter __attribute__((sentinel)) 411251875Speter#endif 412251875Speter ; 413251875Speter 414251875Speter/** 415251875Speter * Iterate over a table running the provided function once for every 416362181Sdim * element in the table. The vp varargs parameter must be a 417251875Speter * list of zero or more (char *) keys followed by a NULL pointer. If 418251875Speter * zero keys are given, the @param comp function will be invoked for 419251875Speter * every element in the table. Otherwise, the function is invoked 420251875Speter * only for those elements matching the keys specified. 421251875Speter * 422362181Sdim * If an invocation of the comp function returns zero, 423251875Speter * iteration will continue using the next specified key, if any. 424251875Speter * 425251875Speter * @param comp The function to run 426251875Speter * @param rec The data to pass as the first argument to the function 427251875Speter * @param t The table to iterate over 428251875Speter * @param vp List of zero or more (char *) keys followed by NULL 429251875Speter * @return FALSE if one of the comp() iterations returned zero; TRUE if all 430251875Speter * iterations returned non-zero 431362181Sdim * @see apr_table_do_callback_fn_t @see apr_table_do 432251875Speter */ 433251875SpeterAPR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp, 434251875Speter void *rec, const apr_table_t *t, va_list vp); 435251875Speter 436251875Speter/** flag for overlap to use apr_table_setn */ 437251875Speter#define APR_OVERLAP_TABLES_SET (0) 438251875Speter/** flag for overlap to use apr_table_mergen */ 439251875Speter#define APR_OVERLAP_TABLES_MERGE (1) 440362181Sdim/** flag for overlap to use apr_table_addn */ 441362181Sdim#define APR_OVERLAP_TABLES_ADD (2) 442251875Speter/** 443251875Speter * For each element in table b, either use setn or mergen to add the data 444251875Speter * to table a. Which method is used is determined by the flags passed in. 445251875Speter * @param a The table to add the data to. 446251875Speter * @param b The table to iterate over, adding its data to table a 447251875Speter * @param flags How to add the table to table a. One of: 448251875Speter * APR_OVERLAP_TABLES_SET Use apr_table_setn 449251875Speter * APR_OVERLAP_TABLES_MERGE Use apr_table_mergen 450362181Sdim * APR_OVERLAP_TABLES_ADD Use apr_table_addn 451251875Speter * @remark When merging duplicates, the two values are concatenated, 452251875Speter * separated by the string ", ". 453251875Speter * @remark This function is highly optimized, and uses less memory and CPU cycles 454251875Speter * than a function that just loops through table b calling other functions. 455251875Speter */ 456251875Speter/** 457251875Speter * Conceptually, apr_table_overlap does this: 458251875Speter * 459251875Speter * <pre> 460251875Speter * apr_array_header_t *barr = apr_table_elts(b); 461251875Speter * apr_table_entry_t *belt = (apr_table_entry_t *)barr->elts; 462251875Speter * int i; 463251875Speter * 464251875Speter * for (i = 0; i < barr->nelts; ++i) { 465251875Speter * if (flags & APR_OVERLAP_TABLES_MERGE) { 466251875Speter * apr_table_mergen(a, belt[i].key, belt[i].val); 467251875Speter * } 468362181Sdim * else if (flags & APR_OVERLAP_TABLES_ADD) { 469362181Sdim * apr_table_addn(a, belt[i].key, belt[i].val); 470362181Sdim * } 471251875Speter * else { 472251875Speter * apr_table_setn(a, belt[i].key, belt[i].val); 473251875Speter * } 474251875Speter * } 475251875Speter * </pre> 476251875Speter * 477251875Speter * Except that it is more efficient (less space and cpu-time) especially 478251875Speter * when b has many elements. 479251875Speter * 480251875Speter * Notice the assumptions on the keys and values in b -- they must be 481251875Speter * in an ancestor of a's pool. In practice b and a are usually from 482251875Speter * the same pool. 483251875Speter */ 484251875Speter 485251875SpeterAPR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b, 486251875Speter unsigned flags); 487251875Speter 488251875Speter/** 489251875Speter * Eliminate redundant entries in a table by either overwriting 490251875Speter * or merging duplicates. 491251875Speter * 492251875Speter * @param t Table. 493251875Speter * @param flags APR_OVERLAP_TABLES_MERGE to merge, or 494362181Sdim * APR_OVERLAP_TABLES_SET to overwrite, or 495362181Sdim * APR_OVERLAP_TABLES_ADD to add 496251875Speter * @remark When merging duplicates, the two values are concatenated, 497251875Speter * separated by the string ", ". 498251875Speter */ 499251875SpeterAPR_DECLARE(void) apr_table_compress(apr_table_t *t, unsigned flags); 500251875Speter 501251875Speter/** @} */ 502251875Speter 503251875Speter#ifdef __cplusplus 504251875Speter} 505251875Speter#endif 506251875Speter 507251875Speter#endif /* ! APR_TABLES_H */ 508