1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
/* catdvi - get text from DVI files
Copyright (C) 2001 Bjoern Brill <brill@fs.math.uni-frankfurt.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef SPARSE_H
#define SPARSE_H
/* Implements a sparse array (of pointers to void, for universal usability),
* or "sparp" for short. This means that all unassigned entries are assumed
* to be NULL and don't occupy memory.
*
* The assigned entries are stored as the leaves of a
* (2^SPARP_BITS_PER_STAGE)-ary tree of dynamically growing height. Branches
* not leading to an assigned entry are simply not created, and the
* lookup function sparp_read() returns NULL on them.
*
* More precisely, every leaf holds 2^SPARP_BITS_PER_STAGE entries with
* contiguous indices and is created (together with neccessary intermediate
* nodes) as soon as one of those entries is assigned to. The other entries
* in that leaf are NULLed on creation. This is a technical optimization
* (reducing the required tree height by 1) and doesn't affect the described
* semantics.
*
* The memory the assigned _values_ point to is never touched by the
* sparp methods and also not freed by the destructor. If neccessary,
* this is up to the caller. So, technically, there is no problem with
* duplicate values, nor with values pointing to invalid memory.
*/
#include "bytesex.h" /* for uint32 */
typedef uint32 sparp_index_t;
/* Configurable. Must be integral. Signed types may lead to problems
* _if_ you actually call one of the methods with negative index values.
* Using an unsigned index type and have negative index values
* autoconverted to large unsigned ones works allright.
*/
#define SPARP_BITS_PER_STAGE 8
/* Configurable. Need not divide (bits per sparp_index_t) */
typedef union sparp_rec_t {
union sparp_rec_t * p;
void * v;
} sparp_rec_t;
typedef struct sparp_t {
sparp_rec_t head;
signed int max_bits;
signed int max_shift;
sparp_index_t max_index;
} sparp_t;
/* constructor */
void sparp_init(sparp_t * this);
/* destructor */
void sparp_done(sparp_t * this);
/* Assign value v to entry i (creating it if neccessary). */
void sparp_write(sparp_t * this, sparp_index_t i, void * v);
/* Read array entry with index i. Return NULL if unassigned. */
void * sparp_read(sparp_t * this, sparp_index_t i);
/* Get the address of entry i, i.e. the equivalent of (a + i) for
* a normal array a. If the entry was previously unassigned, it will be
* created with _value_ NULL. The function always returns a pointer to an
* assignable lvalue and never NULL (even though the lvalue itself may
* be NULL).
*
* Mainly useful to save the cost of a second lookup in "assign if not
* already assigned" operations.
*
* In contrast to the (a + i) construct for normal arrays, the returned
* pointer can not be used as a "subarray".
*/
void ** sparp_addressof_entry(sparp_t * this, sparp_index_t i);
#endif
|