summaryrefslogtreecommitdiff
path: root/include/libwapcaplet/libwapcaplet.h
blob: b71306c056bd4db20958d7cf2909667fc1075d5b (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/* libwapcaplet.h
 *
 * String internment and management tools.
 *
 * Copyright 2009 The NetSurf Browser Project.
 *		  Daniel Silverstone <dsilvers@netsurf-browser.org>
 */

#ifndef libwapcaplet_h_
#define libwapcaplet_h_

#include <sys/types.h>
#include <stdbool.h>
#include <stdint.h>

/**
 * Memory allocator function type
 *
 * @param ptr The old pointer to reallocate (NULL for new allocations).
 * @param size The size of block to allocate.
 * @param pw The private pointer for the allocator.
 * @return The newly allocated/resized pointer or NULL on error.
 */
typedef void *(*lwc_allocator_fn)(void *ptr, size_t size, void *pw);

/**
 * An interned string.
 */
typedef struct lwc_string_s lwc_string;

/**
 * Result codes which libwapcaplet might return.
 */
typedef enum lwc_error_e {
	lwc_error_ok		= 0,	/**< No error. */
        lwc_error_initialised	= 1,	/**< Library already initialised. */
	lwc_error_oom		= 2,	/**< Out of memory. */
	lwc_error_range		= 3,	/**< Substring internment out of range. */
} lwc_error;

/**
 * The type of a hash value used in libwapcaplet.
 */
typedef uint32_t lwc_hash;

/**
 * Initialise the library.
 *
 * Initialise the library with an allocator function.  All strings
 * interned will be allocated via this function, as will any
 * structures required to manage libwapcaplet.  In this manner, all
 * interned strings are directly comparable, no matter what interned
 * them.
 *
 * @note If you require to know how much memory libwapcaplet is using
 *       then you should use a counting allocator function.
 *
 * @param alloc   The allocator to use for libwapcaplet allocations.
 * @param pw      The private word to pass to \a alloc.
 * @param buckets The number of buckets to use by default, or zero to
 *                allow the implementation to choose for itself.
 * @return        The result of initialising.  If not OK do not use
 *                any further wapcaplet functions.
 */
extern lwc_error lwc_initialise(lwc_allocator_fn alloc, void *pw, lwc_hash buckets);

/**
 * Intern a string.
 *
 * Take a copy of the string data referred to by \a s and \a slen and
 * intern it.  The resulting ::lwc_string can be used for simple and
 * caseless comparisons by ::lwc_string_isequal and
 * ::lwc_string_caseless_isequal respectively.
 *
 * @param s    Pointer to the start of the string to intern.
 * @param slen Length of the string in characters. (Not including any 
 *	       terminators)
 * @param ret  Pointer to ::lwc_string pointer to fill out.
 * @return     Result of operation, if not OK then the value pointed
 *	       to by \a ret will not be valid.
 *
 * @note The memory pointed to by \a s is not referenced by the result.
 * @note If the string was already present, its reference count is
 * incremented rather than allocating more memory.
 *
 * @note The returned string is currently NULL-terminated but this
 *	 will not necessarily be the case in future.  Try not to rely
 *	 on it.
 */
extern lwc_error lwc_intern_string(const char *s, size_t slen,
                                   lwc_string **ret);

/**
 * Intern a substring.
 *
 * Intern a subsequence of the provided ::lwc_string.
 *
 * @param str	   String to acquire substring from.
 * @param ssoffset Substring offset into \a str.
 * @param sslen	   Substring length.
 * @param ret	   Pointer to pointer to ::lwc_string to fill out.
 * @return	   Result of operation, if not OK then the value
 *		   pointed to by \a ret will not be valid.
 */
extern lwc_error lwc_intern_substring(lwc_string *str,
                                      size_t ssoffset, size_t sslen,
                                      lwc_string **ret);

/**
 * Increment the reference count on an lwc_string.
 *
 * This increases the reference count on the given string. You should
 * use this when copying a string pointer into a persistent data
 * structure.
 *
 * @verb
 *   myobject->str = lwc_string_ref(myparent->str);
 * @endverb
 *
 * @param str The string to create another reference to.
 * @return    The string pointer to use in your new data structure.
 *
 * @note Use this if copying the string and intending both sides to retain
 * ownership.
 */
extern lwc_string *lwc_string_ref(lwc_string *str);

/**
 * Release a reference on an lwc_string.
 *
 * This decreases the reference count on the given ::lwc_string.
 *
 * @param str The string to unref.
 * @return    The result of the operation, if not OK then the string
 *	      was not unreffed.
 *
 * @note If the reference count reaches zero then the string will be
 *       freed.
 */
extern void lwc_string_unref(lwc_string *str);

/**
 * Check if two interned strings are equal.
 *
 * @param str1 The first string in the comparison.
 * @param str2 The second string in the comparison.
 * @param ret  A pointer to a boolean to be filled out with the result.
 * @return     Result of operation, if not ok then value pointed to
 *	       by \a ret will not be valid.
 */
#define lwc_string_isequal(str1, str2, ret) \
	(*ret = (str1 == str2)), lwc_error_ok

/**
 * Check if two interned strings are case-insensitively equal.
 *
 * @param str1 The first string in the comparison.
 * @param str2 The second string in the comparison.
 * @param ret  A pointer to a boolean to be filled out with the result.
 * @return     Result of operation, if not ok then value pointed to
 *	       by \a ret will not be valid.
 */
extern lwc_error lwc_string_caseless_isequal(lwc_string *str1,
                                             lwc_string *str2,
                                             bool *ret);
/**
 * Retrieve the data pointer for an interned string.
 *
 * @param str The string to retrieve the data pointer for.
 * @return    The C string data pointer for \a str.
 *
 * @note The data we point at belongs to the string and will
 *	 die with the string. Keep a ref if you need it.
 * @note You may not rely on the NULL termination of the strings
 *	 in future.  Any code relying on it currently should be
 *	 modified to use ::lwc_string_length if possible.
 */
extern const char *lwc_string_data(lwc_string *str);

/**
 * Retrieve the data length for an interned string.
 *
 * @param str The string to retrieve the length of.
 * @return    The length of \a str.
 */
extern size_t lwc_string_length(lwc_string *str);

/**
 * Retrieve (or compute if unavailable) a hash value for the content of the string.
 *
 * @param str The string to get the hash for.
 * @return    The 32 bit hash of \a str.
 *
 * @note This API should only be used as a convenient way to retrieve a hash
 *	 value for the string. This hash value should not be relied on to be
 *	 unique within an invocation of the program, nor should it be relied upon
 *	 to be stable between invocations of the program. Never use the hash
 *	 value as a way to directly identify the value of the string.
 */
extern uint32_t lwc_string_hash_value(lwc_string *str);

#endif /* libwapcaplet_h_ */