Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3584 sourcerer 1
/* libwapcaplet.h
2
 *
3
 * String internment and management tools.
4
 *
5
 * Copyright 2009 The NetSurf Browser Project.
6
 *		  Daniel Silverstone 
7
 */
8
 
9
#ifndef libwapcaplet_h_
10
#define libwapcaplet_h_
11
 
12
#ifdef __cplusplus
13
extern "C"
14
{
15
#endif
16
 
17
#include 
18
#include 
19
#include 
20
 
21
/**
22
 * The type of a reference counter used in libwapcaplet.
23
 */
24
typedef uint32_t lwc_refcounter;
25
 
26
/**
27
 * The type of a hash value used in libwapcaplet.
28
 */
29
typedef uint32_t lwc_hash;
30
 
31
/**
32
 * An interned string.
33
 *
34
 * NOTE: The contents of this struct are considered *PRIVATE* and may
35
 * change in future revisions.  Do not rely on them whatsoever.
36
 * They're only here at all so that the ref, unref and matches etc can
37
 * use them.
38
 */
39
typedef struct lwc_string_s {
40
        struct lwc_string_s **	prevptr;
41
        struct lwc_string_s *	next;
42
        size_t		len;
43
        lwc_hash	hash;
44
        lwc_refcounter	refcnt;
45
        struct lwc_string_s *	insensitive;
46
} lwc_string;
47
 
48
/**
49
 * String iteration function
50
 *
51
 * @param str A string which has been interned.
52
 * @param pw The private pointer for the allocator.
53
 */
54
typedef void (*lwc_iteration_callback_fn)(lwc_string *str, void *pw);
55
 
56
/**
57
 * Result codes which libwapcaplet might return.
58
 */
59
typedef enum lwc_error_e {
60
	lwc_error_ok		= 0,	/**< No error. */
61
	lwc_error_oom		= 1,	/**< Out of memory. */
62
	lwc_error_range		= 2	/**< Substring internment out of range. */
63
} lwc_error;
64
 
65
/**
66
 * Intern a string.
67
 *
68
 * Take a copy of the string data referred to by \a s and \a slen and
69
 * intern it.  The resulting ::lwc_string can be used for simple and
70
 * caseless comparisons by ::lwc_string_isequal and
71
 * ::lwc_string_caseless_isequal respectively.
72
 *
73
 * @param s    Pointer to the start of the string to intern.
74
 * @param slen Length of the string in characters. (Not including any
75
 *	       terminators)
76
 * @param ret  Pointer to ::lwc_string pointer to fill out.
77
 * @return     Result of operation, if not OK then the value pointed
78
 *	       to by \a ret will not be valid.
79
 *
80
 * @note The memory pointed to by \a s is not referenced by the result.
81
 * @note If the string was already present, its reference count is
82
 * incremented rather than allocating more memory.
83
 *
84
 * @note The returned string is currently NULL-terminated but this
85
 *	 will not necessarily be the case in future.  Try not to rely
86
 *	 on it.
87
 */
88
extern lwc_error lwc_intern_string(const char *s, size_t slen,
89
                                   lwc_string **ret);
90
 
91
/**
92
 * Intern a substring.
93
 *
94
 * Intern a subsequence of the provided ::lwc_string.
95
 *
96
 * @param str	   String to acquire substring from.
97
 * @param ssoffset Substring offset into \a str.
98
 * @param sslen	   Substring length.
99
 * @param ret	   Pointer to pointer to ::lwc_string to fill out.
100
 * @return	   Result of operation, if not OK then the value
101
 *		   pointed to by \a ret will not be valid.
102
 */
103
extern lwc_error lwc_intern_substring(lwc_string *str,
104
                                      size_t ssoffset, size_t sslen,
105
                                      lwc_string **ret);
106
 
107
/**
108
 * Increment the reference count on an lwc_string.
109
 *
110
 * This increases the reference count on the given string. You should
111
 * use this when copying a string pointer into a persistent data
112
 * structure.
113
 *
114
 * @verb
115
 *   myobject->str = lwc_string_ref(myparent->str);
116
 * @endverb
117
 *
118
 * @param str The string to create another reference to.
119
 * @return    The string pointer to use in your new data structure.
120
 *
121
 * @note Use this if copying the string and intending both sides to retain
122
 * ownership.
123
 */
124
#define lwc_string_ref(str) ({lwc_string *__lwc_s = (str); __lwc_s->refcnt++; __lwc_s;})
125
 
126
/**
127
 * Release a reference on an lwc_string.
128
 *
129
 * This decreases the reference count on the given ::lwc_string.
130
 *
131
 * @param str The string to unref.
132
 *
133
 * @note If the reference count reaches zero then the string will be
134
 *       freed. (Ref count of 1 where string is its own insensitve match
135
 *       will also result in the string being freed.)
136
 */
137
#define lwc_string_unref(str) {						\
138
		lwc_string *__lwc_s = (str);					\
139
		__lwc_s->refcnt--;						\
140
		if ((__lwc_s->refcnt == 0) ||					\
141
		    ((__lwc_s->refcnt == 1) && (__lwc_s->insensitive == __lwc_s)))	\
142
			lwc_string_destroy(__lwc_s);				\
143
	}
144
 
145
/**
146
 * Destroy an unreffed lwc_string.
147
 *
148
 * This destroys an lwc_string whose reference count indicates that it should be.
149
 *
150
 * @param str The string to unref.
151
 */
152
extern void lwc_string_destroy(lwc_string *str);
153
 
154
/**
155
 * Check if two interned strings are equal.
156
 *
157
 * @param str1 The first string in the comparison.
158
 * @param str2 The second string in the comparison.
159
 * @param ret  A pointer to a boolean to be filled out with the result.
160
 * @return     Result of operation, if not ok then value pointed to
161
 *	       by \a ret will not be valid.
162
 */
163
#define lwc_string_isequal(str1, str2, ret) \
164
	((*(ret) = ((str1) == (str2))), lwc_error_ok)
165
 
166
/**
167
 * Check if two interned strings are case-insensitively equal.
168
 *
169
 * @param str1 The first string in the comparison.
170
 * @param str2 The second string in the comparison.
171
 * @param ret  A pointer to a boolean to be filled out with the result.
172
 * @return     Result of operation, if not ok then value pointed to
173
 *	       by \a ret will not be valid.
174
 */
175
#define lwc_string_caseless_isequal(_str1,_str2,_ret) ({	\
176
			lwc_error __lwc_err = lwc_error_ok;		\
177
			lwc_string *__lwc_str1 = (_str1);		\
178
			lwc_string *__lwc_str2 = (_str2);		\
179
			bool *__lwc_ret = (_ret);			\
180
								\
181
			if (__lwc_str1->insensitive == NULL) {		\
182
				__lwc_err = lwc__intern_caseless_string(__lwc_str1); \
183
			}						\
184
			if (__lwc_err == lwc_error_ok && __lwc_str2->insensitive == NULL) {	\
185
				__lwc_err = lwc__intern_caseless_string(__lwc_str2); \
186
			}						\
187
			if (__lwc_err == lwc_error_ok)			\
188
				*__lwc_ret = (__lwc_str1->insensitive == __lwc_str2->insensitive); \
189
			__lwc_err;						\
190
		})
191
 
192
/**
193
 * Intern a caseless copy of the passed string.
194
 *
195
 * @param str The string to intern the caseless copy of.
196
 *
197
 * @return    lwc_error_ok if successful, otherwise the
198
 *            error code describing the issue.,
199
 *
200
 * @note This is for "internal" use by the caseless comparison
201
 *       macro and not for users.
202
 */
203
extern lwc_error
204
lwc__intern_caseless_string(lwc_string *str);
205
 
206
/**
207
 * Retrieve the data pointer for an interned string.
208
 *
209
 * @param str The string to retrieve the data pointer for.
210
 * @return    The C string data pointer for \a str.
211
 *
212
 * @note The data we point at belongs to the string and will
213
 *	 die with the string. Keep a ref if you need it.
214
 * @note You may not rely on the NULL termination of the strings
215
 *	 in future.  Any code relying on it currently should be
216
 *	 modified to use ::lwc_string_length if possible.
217
 */
218
#define lwc_string_data(str) ((const char *)((str)+1))
219
 
220
/**
221
 * Retrieve the data length for an interned string.
222
 *
223
 * @param str The string to retrieve the length of.
224
 * @return    The length of \a str.
225
 */
226
#define lwc_string_length(str) ((str)->len)
227
 
228
/**
229
 * Retrieve (or compute if unavailable) a hash value for the content of the string.
230
 *
231
 * @param str The string to get the hash for.
232
 * @return    The 32 bit hash of \a str.
233
 *
234
 * @note This API should only be used as a convenient way to retrieve a hash
235
 *	 value for the string. This hash value should not be relied on to be
236
 *	 unique within an invocation of the program, nor should it be relied upon
237
 *	 to be stable between invocations of the program. Never use the hash
238
 *	 value as a way to directly identify the value of the string.
239
 */
240
#define lwc_string_hash_value(str) ((str)->hash)
241
 
242
/**
243
 * Iterate the context and return every string in it.
244
 *
245
 * @param cb The callback to give the string to.
246
 * @param pw The private word for the callback.
247
 */
248
extern void lwc_iterate_strings(lwc_iteration_callback_fn cb, void *pw);
249
 
250
#ifdef __cplusplus
251
}
252
#endif
253
 
254
#endif /* libwapcaplet_h_ */