1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the files COPYING and Copyright.html. COPYING can be found at the root *
9 * of the source code distribution tree; Copyright.html can be found at the *
10 * root level of an installed copy of the electronic HDF5 document set and *
11 * is linked from the top-level documents page. It can also be found at *
12 * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
13 * access to either file, you may request a copy from help@hdfgroup.org. *
14 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15
16 /*
17 * Reference counted string algorithms.
18 *
19 * These are used for various internal strings which get copied multiple times.
20 *
21 */
22
23
24 #include "H5Eprivate.h" /* Error handling */
25 #include "H5FLprivate.h" /* Free lists */
26 #include "H5RSprivate.h" /* Reference-counted strings */
27
28 /* Private typedefs & structs */
29 struct H5RS_str_t {
30 char *s; /* String to be reference counted */
31 unsigned wrapped; /* Indicates that the string to be ref-counted is not copied */
32 unsigned n; /* Reference count of number of pointers sharing string */
33 };
34
35 /* Declare a free list to manage the H5RS_str_t struct */
36 H5FL_DEFINE_STATIC(H5RS_str_t);
37
38 /* Declare the PQ free list for the wrapped strings */
39 H5FL_BLK_DEFINE(str_buf);
40
41
42 /*--------------------------------------------------------------------------
43 NAME
44 H5RS_xstrdup
45 PURPOSE
46 Duplicate the string being reference counted
47 USAGE
48 char *H5RS_xstrdup(s)
49 const char *s; IN: String to duplicate
50
51 RETURNS
52 Returns a pointer to a new string on success, NULL on failure.
53 DESCRIPTION
54 Duplicate a string buffer being reference counted. Use this instead of
55 [H5MM_][x]strdup, in order to use the free-list memory routines.
56 GLOBAL VARIABLES
57 COMMENTS, BUGS, ASSUMPTIONS
58 EXAMPLES
59 REVISION LOG
60 --------------------------------------------------------------------------*/
61 static char *
H5RS_xstrdup(const char * s)62 H5RS_xstrdup(const char *s)
63 {
64 char *ret_value; /* Return value */
65
66 FUNC_ENTER_NOAPI_NOINIT_NOERR
67
68 if(s) {
69 size_t len = HDstrlen(s) + 1;
70
71 ret_value = (char *)H5FL_BLK_MALLOC(str_buf, len);
72 HDassert(ret_value);
73 HDstrncpy(ret_value, s, len);
74 } /* end if */
75 else
76 ret_value = NULL;
77
78 FUNC_LEAVE_NOAPI(ret_value)
79 } /* end H5RS_xstrdup() */
80
81
82 /*--------------------------------------------------------------------------
83 NAME
84 H5RS_create
85 PURPOSE
86 Create a reference counted string
87 USAGE
88 H5RS_str_t *H5RS_create(s)
89 const char *s; IN: String to initialize ref-counted string with
90
91 RETURNS
92 Returns a pointer to a new ref-counted string on success, NULL on failure.
93 DESCRIPTION
94 Create a reference counted string. The string passed in is copied into an
95 internal buffer.
96 GLOBAL VARIABLES
97 COMMENTS, BUGS, ASSUMPTIONS
98 EXAMPLES
99 REVISION LOG
100 --------------------------------------------------------------------------*/
101 H5RS_str_t *
H5RS_create(const char * s)102 H5RS_create(const char *s)
103 {
104 H5RS_str_t *ret_value; /* Return value */
105
106 FUNC_ENTER_NOAPI(NULL)
107
108 /* Allocate ref-counted string structure */
109 if(NULL == (ret_value = H5FL_MALLOC(H5RS_str_t)))
110 HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed")
111
112 /* Set the internal fields */
113 ret_value->s = H5RS_xstrdup(s);
114 ret_value->wrapped = 0;
115 ret_value->n = 1;
116
117 done:
118 FUNC_LEAVE_NOAPI(ret_value)
119 } /* end H5RS_create() */
120
121
122 /*--------------------------------------------------------------------------
123 NAME
124 H5RS_wrap
125 PURPOSE
126 "Wrap" a reference counted string around an existing string
127 USAGE
128 H5RS_str_t *H5RS_wrap(s)
129 const char *s; IN: String to wrap ref-counted string around
130
131 RETURNS
132 Returns a pointer to a new ref-counted string on success, NULL on failure.
133 DESCRIPTION
134 Wrap a reference counted string around an existing string, which is not
135 duplicated, unless its reference count gets incremented.
136 GLOBAL VARIABLES
137 COMMENTS, BUGS, ASSUMPTIONS
138 EXAMPLES
139 REVISION LOG
140 --------------------------------------------------------------------------*/
141 H5RS_str_t *
H5RS_wrap(const char * s)142 H5RS_wrap(const char *s)
143 {
144 H5RS_str_t *ret_value; /* Return value */
145
146 FUNC_ENTER_NOAPI(NULL)
147
148 /* Allocate ref-counted string structure */
149 if(NULL == (ret_value = H5FL_MALLOC(H5RS_str_t)))
150 HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed")
151
152 /* Set the internal fields */
153 ret_value->s = (char *)s; /* (Cast away const OK - QAK) */
154 ret_value->wrapped = 1;
155 ret_value->n = 1;
156
157 done:
158 FUNC_LEAVE_NOAPI(ret_value)
159 } /* end H5RS_wrap() */
160
161
162 /*--------------------------------------------------------------------------
163 NAME
164 H5RS_own
165 PURPOSE
166 Transfer ownership of a regular string to a reference counted string
167 USAGE
168 H5RS_str_t *H5RS_own(s)
169 const char *s; IN: String to transfer ownership of
170
171 RETURNS
172 Returns a pointer to a new ref-counted string on success, NULL on failure.
173 DESCRIPTION
174 Transfer ownership of a dynamically allocated string to a reference counted
175 string. The routine which passed in the string should not attempt to free
176 it, the reference counting string routines will do that when the reference
177 count drops to zero.
178 GLOBAL VARIABLES
179 COMMENTS, BUGS, ASSUMPTIONS
180 EXAMPLES
181 REVISION LOG
182 --------------------------------------------------------------------------*/
183 H5RS_str_t *
H5RS_own(char * s)184 H5RS_own(char *s)
185 {
186 H5RS_str_t *ret_value; /* Return value */
187
188 FUNC_ENTER_NOAPI(NULL)
189
190 /* Allocate ref-counted string structure */
191 if(NULL == (ret_value = H5FL_MALLOC(H5RS_str_t)))
192 HGOTO_ERROR(H5E_RS, H5E_NOSPACE, NULL, "memory allocation failed")
193
194 /* Set the internal fields */
195 ret_value->s = s;
196 ret_value->wrapped = 0;
197 ret_value->n = 1;
198
199 done:
200 FUNC_LEAVE_NOAPI(ret_value)
201 } /* end H5RS_own() */
202
203
204 /*--------------------------------------------------------------------------
205 NAME
206 H5RS_decr
207 PURPOSE
208 Decrement the reference count for a ref-counted string
209 USAGE
210 herr_t H5RS_decr(rs)
211 H5RS_str_t *rs; IN/OUT: Ref-counted string to decrement count of
212
213 RETURNS
214 Non-negative on success/Negative on failure
215 DESCRIPTION
216 Decrement the reference count for a reference counted string. If the
217 reference count drops to zero, the reference counted string is deleted.
218 GLOBAL VARIABLES
219 COMMENTS, BUGS, ASSUMPTIONS
220 EXAMPLES
221 REVISION LOG
222 --------------------------------------------------------------------------*/
223 herr_t
H5RS_decr(H5RS_str_t * rs)224 H5RS_decr(H5RS_str_t *rs)
225 {
226 FUNC_ENTER_NOAPI_NOINIT_NOERR
227
228 /* Sanity check */
229 HDassert(rs);
230 HDassert(rs->n > 0);
231
232 /* Decrement reference count for string */
233 if((--rs->n) == 0) {
234 if(!rs->wrapped)
235 rs->s = (char *)H5FL_BLK_FREE(str_buf, rs->s);
236 rs = H5FL_FREE(H5RS_str_t, rs);
237 } /* end if */
238
239 FUNC_LEAVE_NOAPI(SUCCEED)
240 } /* end H5RS_decr() */
241
242
243 /*--------------------------------------------------------------------------
244 NAME
245 H5RS_incr
246 PURPOSE
247 Increment the reference count for a ref-counted string
248 USAGE
249 herr_t H5RS_incr(rs)
250 H5RS_str_t *rs; IN/OUT: Ref-counted string to increment count of
251
252 RETURNS
253 Non-negative on success/Negative on failure
254 DESCRIPTION
255 Increment the reference count for a reference counted string.
256 GLOBAL VARIABLES
257 COMMENTS, BUGS, ASSUMPTIONS
258 EXAMPLES
259 REVISION LOG
260 --------------------------------------------------------------------------*/
261 herr_t
H5RS_incr(H5RS_str_t * rs)262 H5RS_incr(H5RS_str_t *rs)
263 {
264 FUNC_ENTER_NOAPI_NOINIT_NOERR
265
266 /* Sanity check */
267 HDassert(rs);
268 HDassert(rs->n > 0);
269
270 /* If the ref-counted string started life as a wrapper around an existing
271 * string, duplicate the string now, so that the wrapped string can go out
272 * scope appropriately.
273 */
274 if(rs->wrapped) {
275 rs->s = H5RS_xstrdup(rs->s);
276 rs->wrapped = 0;
277 } /* end if */
278
279 /* Increment reference count for string */
280 rs->n++;
281
282 FUNC_LEAVE_NOAPI(SUCCEED)
283 } /* end H5RS_incr() */
284
285
286 /*--------------------------------------------------------------------------
287 NAME
288 H5RS_dup
289 PURPOSE
290 "Duplicate" a ref-counted string
291 USAGE
292 H5RS_str_t H5RS_dup(rs)
293 H5RS_str_t *rs; IN/OUT: Ref-counted string to "duplicate"
294
295 RETURNS
296 Returns a pointer to ref-counted string on success, NULL on failure.
297 DESCRIPTION
298 Increment the reference count for the reference counted string and return
299 a pointer to it.
300 GLOBAL VARIABLES
301 COMMENTS, BUGS, ASSUMPTIONS
302 EXAMPLES
303 REVISION LOG
304 --------------------------------------------------------------------------*/
305 H5RS_str_t *
H5RS_dup(H5RS_str_t * ret_value)306 H5RS_dup(H5RS_str_t *ret_value)
307 {
308 FUNC_ENTER_NOAPI_NOINIT_NOERR
309
310 /* Check for valid reference counted string */
311 if(ret_value != NULL)
312 /* Increment reference count for string */
313 ret_value->n++;
314
315 FUNC_LEAVE_NOAPI(ret_value)
316 } /* end H5RS_dup() */
317
318
319 /*--------------------------------------------------------------------------
320 NAME
321 H5RS_dup_str
322 PURPOSE
323 "Duplicate" a regular string into a ref-counted string
324 USAGE
325 H5RS_str_t H5RS_dup_str(s)
326 const char *s; IN: Regular string to duplicate
327
328 RETURNS
329 Returns a pointer to ref-counted string on success, NULL on failure.
330 DESCRIPTION
331 Duplicate a regular string into a ref-counted string.
332 GLOBAL VARIABLES
333 COMMENTS, BUGS, ASSUMPTIONS
334 EXAMPLES
335 REVISION LOG
336 --------------------------------------------------------------------------*/
337 H5RS_str_t *
H5RS_dup_str(const char * s)338 H5RS_dup_str(const char *s)
339 {
340 char *new_str; /* Duplicate of string */
341 size_t path_len; /* Length of the path */
342 H5RS_str_t *ret_value;
343
344 FUNC_ENTER_NOAPI(NULL)
345
346 /* Sanity check */
347 HDassert(s);
348
349 /* Get the length of the string */
350 path_len = HDstrlen(s);
351
352 /* Allocate space for the string */
353 if(NULL == (new_str = (char *)H5FL_BLK_MALLOC(str_buf, path_len + 1)))
354 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
355
356 /* Copy name for full path */
357 HDstrncpy(new_str, s, (path_len + 1));
358
359 /* Create reference counted string for path */
360 ret_value = H5RS_own(new_str);
361
362 done:
363 FUNC_LEAVE_NOAPI(ret_value)
364 } /* end H5RS_dup_str() */
365
366
367 /*--------------------------------------------------------------------------
368 NAME
369 H5RS_cmp
370 PURPOSE
371 Compare two ref-counted strings
372 USAGE
373 int H5RS_cmp(rs1,rs2)
374 const H5RS_str_t *rs1; IN: First Ref-counted string to compare
375 const H5RS_str_t *rs2; IN: Second Ref-counted string to compare
376
377 RETURNS
378 Returns positive, negative or 0 for comparison of two r-strings [same as
379 strcmp()]
380 DESCRIPTION
381 Compare two ref-counted strings and return a value indicating their sort
382 order [same as strcmp()]
383 GLOBAL VARIABLES
384 COMMENTS, BUGS, ASSUMPTIONS
385 EXAMPLES
386 REVISION LOG
387 --------------------------------------------------------------------------*/
388 int
H5RS_cmp(const H5RS_str_t * rs1,const H5RS_str_t * rs2)389 H5RS_cmp(const H5RS_str_t *rs1, const H5RS_str_t *rs2)
390 {
391 /* Can't return invalid value from this function */
392 FUNC_ENTER_NOAPI_NOINIT_NOERR
393
394 /* Sanity check */
395 HDassert(rs1);
396 HDassert(rs1->s);
397 HDassert(rs2);
398 HDassert(rs2->s);
399
400 FUNC_LEAVE_NOAPI(HDstrcmp(rs1->s, rs2->s))
401 } /* end H5RS_cmp() */
402
403
404 /*--------------------------------------------------------------------------
405 NAME
406 H5RS_len
407 PURPOSE
408 Compute the length of a ref-counted string
409 USAGE
410 ssize_t H5RS_cmp(rs)
411 const H5RS_str_t *rs; IN: Ref-counted string to compute length of
412
413 RETURNS
414 Returns non-negative value on success, negative value on failure
415 DESCRIPTION
416 Compute the length of a ref-counted string. [same as strlen()]
417 GLOBAL VARIABLES
418 COMMENTS, BUGS, ASSUMPTIONS
419 EXAMPLES
420 REVISION LOG
421 --------------------------------------------------------------------------*/
422 ssize_t
H5RS_len(const H5RS_str_t * rs)423 H5RS_len(const H5RS_str_t *rs)
424 {
425 FUNC_ENTER_NOAPI_NOINIT_NOERR
426
427 /* Sanity check */
428 HDassert(rs);
429 HDassert(rs->s);
430
431 FUNC_LEAVE_NOAPI((ssize_t)HDstrlen(rs->s))
432 } /* end H5RS_len() */
433
434
435 /*--------------------------------------------------------------------------
436 NAME
437 H5RS_get_str
438 PURPOSE
439 Get a pointer to the internal string contained in a ref-counted string
440 USAGE
441 char *H5RS_get_str(rs)
442 const H5RS_str_t *rs; IN: Ref-counted string to get internal string from
443
444 RETURNS
445 Returns a pointer to the internal string being ref-counted on success,
446 NULL on failure.
447 DESCRIPTION
448 Gets a pointer to the internal string being reference counted. This
449 pointer is volatile and might be invalid is further calls to the H5RS
450 API are made.
451 GLOBAL VARIABLES
452 COMMENTS, BUGS, ASSUMPTIONS
453 EXAMPLES
454 REVISION LOG
455 --------------------------------------------------------------------------*/
456 char *
H5RS_get_str(const H5RS_str_t * rs)457 H5RS_get_str(const H5RS_str_t *rs)
458 {
459 FUNC_ENTER_NOAPI_NOINIT_NOERR
460
461 /* Sanity check */
462 HDassert(rs);
463 HDassert(rs->s);
464
465 FUNC_LEAVE_NOAPI(rs->s)
466 } /* end H5RS_get_str() */
467
468
469 /*--------------------------------------------------------------------------
470 NAME
471 H5RS_get_count
472 PURPOSE
473 Get the reference count for a ref-counted string
474 USAGE
475 unsigned H5RS_get_count(rs)
476 const H5RS_str_t *rs; IN: Ref-counted string to get internal count from
477
478 RETURNS
479 Returns the number of references to the internal string being ref-counted on success,
480 0 on failure.
481 DESCRIPTION
482 Gets the count of references to the reference counted string.
483 GLOBAL VARIABLES
484 COMMENTS, BUGS, ASSUMPTIONS
485 EXAMPLES
486 REVISION LOG
487 --------------------------------------------------------------------------*/
488 unsigned
H5RS_get_count(const H5RS_str_t * rs)489 H5RS_get_count(const H5RS_str_t *rs)
490 {
491 FUNC_ENTER_NOAPI_NOINIT_NOERR
492
493 /* Sanity check */
494 HDassert(rs);
495 HDassert(rs->n > 0);
496
497 FUNC_LEAVE_NOAPI(rs->n)
498 } /* end H5RS_get_count() */
499
500