1 /* -*- Mode: c; c-basic-offset: 2 -*-
2 *
3 * rdf_hash.c - RDF Hash interface - set of (key: value) pairs with dups
4 *
5 * Copyright (C) 2000-2008, David Beckett http://www.dajobe.org/
6 * Copyright (C) 2000-2005, University of Bristol, UK http://www.bristol.ac.uk/
7 *
8 * This package is Free Software and part of Redland http://librdf.org/
9 *
10 * It is licensed under the following three licenses as alternatives:
11 * 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
12 * 2. GNU General Public License (GPL) V2 or any newer version
13 * 3. Apache License, V2.0 or any newer version
14 *
15 * You may not use this file except in compliance with at least one of
16 * the above three licenses.
17 *
18 * See LICENSE.html or LICENSE.txt at the top of this package for the
19 * complete terms and further detail along with the license texts for
20 * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
21 *
22 *
23 */
24
25
26 #ifdef HAVE_CONFIG_H
27 #include <rdf_config.h>
28 #endif
29
30 #ifdef WIN32
31 #include <win32_rdf_config.h>
32 #endif
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdarg.h>
37 #include <ctype.h>
38 #include <sys/types.h>
39
40 #ifdef HAVE_STDLIB_H
41 #include <stdlib.h> /* for strtol */
42 #endif
43
44 #include <redland.h>
45
46 #include <rdf_hash.h>
47 #include <rdf_heuristics.h>
48
49 #ifndef STANDALONE
50
51 /* prototypes for helper functions */
52 static void librdf_delete_hash_factories(librdf_world *world);
53
54 static void librdf_init_hash_datums(librdf_world *world);
55 static void librdf_free_hash_datums(librdf_world *world);
56
57
58 /* prototypes for iterator for getting all keys and values */
59 static int librdf_hash_get_all_iterator_is_end(void* iterator);
60 static int librdf_hash_get_all_iterator_next_method(void* iterator);
61 static void* librdf_hash_get_all_iterator_get_method(void* iterator, int);
62 static void librdf_hash_get_all_iterator_finished(void* iterator);
63
64 /* prototypes for iterator for getting all keys */
65 static int librdf_hash_keys_iterator_is_end(void* iterator);
66 static int librdf_hash_keys_iterator_next_method(void* iterator);
67 static void* librdf_hash_keys_iterator_get_method(void* iterator, int);
68 static void librdf_hash_keys_iterator_finished(void* iterator);
69
70
71
72
73 /**
74 * librdf_init_hash:
75 *
76 * INTERNAL - Initialise the hash module.
77 *
78 * Initialises and registers all
79 * compiled hash modules. Must be called before using any of the hash
80 * factory functions such as librdf_get_hash_factory()
81 * @world: redland world object
82 **/
83 void
librdf_init_hash(librdf_world * world)84 librdf_init_hash(librdf_world *world)
85 {
86 /* Init hash datum cache */
87 librdf_init_hash_datums(world);
88 #ifdef HAVE_BDB_HASH
89 librdf_init_hash_bdb(world);
90 #endif
91 /* Always have hash in memory implementation available */
92 librdf_init_hash_memory(world);
93 }
94
95
96 /**
97 * librdf_finish_hash:
98 * @world: redland world object
99 *
100 * INTERNAL - Terminate the hash module.
101 *
102 **/
103 void
librdf_finish_hash(librdf_world * world)104 librdf_finish_hash(librdf_world *world)
105 {
106 librdf_delete_hash_factories(world);
107 librdf_free_hash_datums(world);
108 }
109
110
111
112 /* helper functions */
113 static void
librdf_delete_hash_factories(librdf_world * world)114 librdf_delete_hash_factories(librdf_world *world)
115 {
116 librdf_hash_factory *factory, *next;
117
118 for(factory=world->hashes; factory; factory=next) {
119 next=factory->next;
120 LIBRDF_FREE(librdf_hash_factory, factory->name);
121 LIBRDF_FREE(librdf_hash_factory, factory);
122 }
123 world->hashes=NULL;
124
125 }
126
127
128
129 /* hash datums structures */
130
131 static void
librdf_init_hash_datums(librdf_world * world)132 librdf_init_hash_datums(librdf_world *world)
133 {
134 world->hash_datums_list=NULL;
135 }
136
137
138 static void
librdf_free_hash_datums(librdf_world * world)139 librdf_free_hash_datums(librdf_world *world)
140 {
141 librdf_hash_datum *datum, *next;
142
143 #ifdef WITH_THREADS
144 if(world->hash_datums_mutex)
145 pthread_mutex_lock(world->hash_datums_mutex);
146 #endif
147
148 for(datum = world->hash_datums_list; datum; datum = next) {
149 next = datum->next;
150 LIBRDF_FREE(librdf_hash_datum, datum);
151 }
152 world->hash_datums_list = NULL;
153
154 #ifdef WITH_THREADS
155 if(world->hash_datums_mutex)
156 pthread_mutex_unlock(world->hash_datums_mutex);
157 #endif
158 }
159
160
161 /**
162 * librdf_new_hash_datum:
163 * @world: redland world object
164 * @data: data to store
165 * @size: size of data
166 *
167 * Constructor - Create a new #librdf_hash_datum object.
168 *
169 * Return value: New #librdf_hash_datum object or NULL on failure
170 **/
171 librdf_hash_datum*
librdf_new_hash_datum(librdf_world * world,void * data,size_t size)172 librdf_new_hash_datum(librdf_world *world, void *data, size_t size)
173 {
174 librdf_hash_datum *datum;
175
176 librdf_world_open(world);
177
178 #ifdef WITH_THREADS
179 pthread_mutex_lock(world->hash_datums_mutex);
180 #endif
181
182 /* get one from free list, or allocate new one */
183 if((datum = world->hash_datums_list)) {
184 world->hash_datums_list = datum->next;
185 } else {
186 datum = LIBRDF_CALLOC(librdf_hash_datum*, 1, sizeof(*datum));
187 if(datum)
188 datum->world = world;
189 }
190
191 #ifdef WITH_THREADS
192 pthread_mutex_unlock(world->hash_datums_mutex);
193 #endif
194
195 if(datum) {
196 datum->data = data;
197 datum->size = size;
198 }
199
200 return datum;
201 }
202
203
204 /**
205 * librdf_free_hash_datum:
206 * @datum: hash datum object
207 *
208 * Destructor - destroy a #librdf_hash_datum object.
209 *
210 **/
211 void
librdf_free_hash_datum(librdf_hash_datum * datum)212 librdf_free_hash_datum(librdf_hash_datum *datum)
213 {
214 if(!datum)
215 return;
216
217 if(datum->data) {
218 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
219 LIBRDF_DEBUG2("Freeing datum data, %p\n", datum);
220 #endif
221 LIBRDF_FREE(char*, datum->data);
222 datum->data = NULL;
223 }
224
225 #ifdef WITH_THREADS
226 pthread_mutex_lock(datum->world->hash_datums_mutex);
227 #endif
228
229 datum->next = datum->world->hash_datums_list;
230 datum->world->hash_datums_list = datum;
231
232 #ifdef WITH_THREADS
233 pthread_mutex_unlock(datum->world->hash_datums_mutex);
234 #endif
235 }
236
237
238 /* class methods */
239
240 /**
241 * librdf_hash_register_factory:
242 * @world: redland world object
243 * @name: the hash factory name
244 * @factory: pointer to function to call to register the factory
245 *
246 * Register a hash factory.
247 *
248 **/
249 REDLAND_EXTERN_C
250 void
librdf_hash_register_factory(librdf_world * world,const char * name,void (* factory)(librdf_hash_factory *))251 librdf_hash_register_factory(librdf_world *world, const char *name,
252 void (*factory) (librdf_hash_factory*))
253 {
254 librdf_hash_factory *hash;
255
256 librdf_world_open(world);
257
258 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
259 LIBRDF_DEBUG2("Received registration for hash %s\n", name);
260 #endif
261
262 for(hash = world->hashes; hash; hash = hash->next ) {
263 if(!strcmp(hash->name, name)) {
264 librdf_log(world, 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
265 "hash %s already registered", hash->name);
266 return;
267 }
268 }
269
270 hash = LIBRDF_CALLOC(librdf_hash_factory*, 1, sizeof(*hash));
271 if(!hash)
272 goto oom;
273
274 hash->name = LIBRDF_MALLOC(char*, strlen(name) + 1);
275 if(!hash->name)
276 goto oom_tidy;
277 strcpy(hash->name, name);
278
279 hash->next = world->hashes;
280 world->hashes = hash;
281
282 /* Call the hash registration function on the new object */
283 (*factory)(hash);
284
285 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
286 LIBRDF_DEBUG3("%s has context size %d\n", name, hash->context_length);
287 #endif
288
289 return;
290
291 oom_tidy:
292 LIBRDF_FREE(librdf_hash, hash);
293 oom:
294 LIBRDF_FATAL1(world, LIBRDF_FROM_HASH, "Out of memory");
295 }
296
297
298 /**
299 * librdf_get_hash_factory:
300 * @world: redland world object
301 * @name: the factory name or NULL for the default factory
302 *
303 * Get a hash factory by name.
304 *
305 * FIXME: several bits of code assume the default hash factory is
306 * in memory.
307 *
308 * Return value: the factory object or NULL if there is no such factory
309 **/
310 librdf_hash_factory*
librdf_get_hash_factory(librdf_world * world,const char * name)311 librdf_get_hash_factory(librdf_world *world, const char *name)
312 {
313 librdf_hash_factory *factory;
314
315 librdf_world_open(world);
316
317 /* return 1st hash if no particular one wanted - why? */
318 if(!name) {
319 factory=world->hashes;
320 if(!factory) {
321 LIBRDF_DEBUG1("No (default) hashes registered\n");
322 return NULL;
323 }
324 } else {
325 for(factory=world->hashes; factory; factory=factory->next) {
326 if(!strcmp(factory->name, name)) {
327 break;
328 }
329 }
330 /* else FACTORY name not found */
331 if(!factory)
332 return NULL;
333 }
334
335 return factory;
336 }
337
338
339
340 /**
341 * librdf_new_hash:
342 * @world: redland world object
343 * @name: factory name
344 *
345 * Constructor - create a new #librdf_hash object.
346 *
347 * Return value: a new #librdf_hash object or NULL on failure
348 */
349 librdf_hash*
librdf_new_hash(librdf_world * world,const char * name)350 librdf_new_hash(librdf_world *world, const char* name)
351 {
352 librdf_hash_factory *factory;
353
354 librdf_world_open(world);
355
356 factory=librdf_get_hash_factory(world, name);
357 if(!factory)
358 return NULL;
359
360 return librdf_new_hash_from_factory(world, factory);
361 }
362
363
364 /**
365 * librdf_new_hash_from_factory:
366 * @world: redland world object
367 * @factory: the factory to use to construct the hash
368 *
369 * Constructor - create a new #librdf_hash object from a factory.
370 *
371 * Return value: a new #librdf_hash object or NULL on failure
372 */
373 librdf_hash*
librdf_new_hash_from_factory(librdf_world * world,librdf_hash_factory * factory)374 librdf_new_hash_from_factory(librdf_world *world,
375 librdf_hash_factory* factory)
376 {
377 librdf_hash* h;
378
379 librdf_world_open(world);
380
381 h = LIBRDF_CALLOC(librdf_hash*, 1, sizeof(*h));
382 if(!h)
383 return NULL;
384
385 h->context = LIBRDF_CALLOC(void*, 1, factory->context_length);
386 if(!h->context) {
387 librdf_free_hash(h);
388 return NULL;
389 }
390
391 h->world=world;
392
393 h->factory=factory;
394
395 /* call factory constructor */
396 if(h->factory->create(h, h->context)) {
397 librdf_free_hash(h);
398 return NULL;
399 }
400
401 return h;
402 }
403
404
405 /**
406 * librdf_new_hash_from_string:
407 * @world: redland world object
408 * @name: hash name
409 * @string: hash encoded as a string
410 *
411 * Constructor - create a new #librdf_hash object from a string.
412 *
413 * See #librdf_hash_from_string for the string format.
414 *
415 * Return value: a new #librdf_hash object or NULL on failure
416 */
417 librdf_hash*
librdf_new_hash_from_string(librdf_world * world,const char * name,const char * string)418 librdf_new_hash_from_string(librdf_world *world, const char *name,
419 const char *string)
420 {
421 librdf_hash* hash;
422
423 librdf_world_open(world);
424
425 hash=librdf_new_hash(world, name);
426 if(!hash)
427 return NULL;
428
429 if(librdf_hash_from_string(hash, string)) {
430 librdf_free_hash(hash);
431 return NULL;
432 }
433
434 return hash;
435 }
436
437
438 /**
439 * librdf_new_hash_from_array_of_strings:
440 * @world: redland world object
441 * @name: hash name
442 * @array: address of the start of the array of char* pointers
443 *
444 * Constructor - create a new #librdf_hash object from an array of strings.
445 *
446 * Return value: a new #librdf_hash object or NULL on failure
447 */
448 librdf_hash*
librdf_new_hash_from_array_of_strings(librdf_world * world,const char * name,const char ** array)449 librdf_new_hash_from_array_of_strings(librdf_world *world, const char *name,
450 const char **array)
451 {
452 librdf_hash* hash;
453
454 librdf_world_open(world);
455
456 hash=librdf_new_hash(world, name);
457 if(!hash)
458 return NULL;
459
460 if(librdf_hash_from_array_of_strings(hash, array)) {
461 librdf_free_hash(hash);
462 return NULL;
463 }
464
465 return hash;
466 }
467
468
469 /**
470 * librdf_new_hash_from_hash:
471 * @old_hash: the hash to use to construct the hash
472 *
473 * Copy Constructor - create a new #librdf_hash object from an existing one.
474 *
475 * Return value: a new #librdf_hash object or NULL on failure
476 */
477 librdf_hash*
librdf_new_hash_from_hash(librdf_hash * old_hash)478 librdf_new_hash_from_hash(librdf_hash* old_hash)
479 {
480 librdf_hash* hash;
481
482 hash = LIBRDF_CALLOC(librdf_hash*, 1, sizeof(*hash));
483 if(!hash)
484 return NULL;
485
486 hash->world=old_hash->world;
487 hash->factory=old_hash->factory;
488
489 hash->context = LIBRDF_CALLOC(void*, 1, hash->factory->context_length);
490 if(!hash->context) {
491 librdf_free_hash(hash);
492 return NULL;
493 }
494
495 if(old_hash->identifier) {
496 hash->identifier=librdf_heuristic_gen_name(old_hash->identifier);
497 if(!hash->identifier) {
498 librdf_free_hash(hash);
499 return NULL;
500 }
501 }
502
503 if(hash->factory->clone(hash, hash->context, hash->identifier,
504 old_hash->context)) {
505 if(hash->identifier)
506 LIBRDF_FREE(char*, hash->identifier);
507 librdf_free_hash(hash);
508 return NULL;
509 }
510
511 return hash;
512 }
513
514
515 /**
516 * librdf_free_hash:
517 * @hash: hash object
518 *
519 * Destructor - destroy a #librdf_hash object.
520 */
521 void
librdf_free_hash(librdf_hash * hash)522 librdf_free_hash(librdf_hash* hash)
523 {
524 if(!hash)
525 return;
526
527 if(hash->context) {
528 if(hash->is_open)
529 librdf_hash_close(hash);
530 hash->factory->destroy(hash->context);
531 LIBRDF_FREE(librdf_hash_context, hash->context);
532 }
533 LIBRDF_FREE(librdf_hash, hash);
534 }
535
536
537 /* methods */
538
539 /**
540 * librdf_hash_open:
541 * @hash: hash object
542 * @identifier: indentifier for the hash factory - usually a URI or file name
543 * @mode: hash access mode
544 * @is_writable: is hash writable?
545 * @is_new: is hash new?
546 * @options: a hash of options for the hash factory or NULL if there are none.
547 *
548 * Start a hash association .
549 *
550 * This method opens and/or creates a new hash with any resources it
551 * needs.
552 *
553 * Return value: non 0 on failure
554 **/
555 int
librdf_hash_open(librdf_hash * hash,const char * identifier,int mode,int is_writable,int is_new,librdf_hash * options)556 librdf_hash_open(librdf_hash* hash, const char *identifier,
557 int mode, int is_writable, int is_new,
558 librdf_hash* options)
559 {
560 int status;
561
562 if(identifier) {
563 hash->identifier = LIBRDF_MALLOC(char*, strlen(identifier) + 1);
564 if(!hash->identifier)
565 return 1;
566 strcpy(hash->identifier, identifier);
567 }
568 status=hash->factory->open(hash->context, identifier,
569 mode, is_writable, is_new,
570 options);
571 if(!status)
572 hash->is_open=1;
573 return status;
574 }
575
576
577 /**
578 * librdf_hash_close:
579 * @hash: hash object
580 *
581 * End a hash association.
582 *
583 * Return value: non 0 on failure
584 **/
585 int
librdf_hash_close(librdf_hash * hash)586 librdf_hash_close(librdf_hash* hash)
587 {
588 hash->is_open=0;
589 if(hash->identifier) {
590 LIBRDF_FREE(char*, hash->identifier);
591 hash->identifier=NULL;
592 }
593 return hash->factory->close(hash->context);
594 }
595
596
597 /**
598 * librdf_hash_values_count:
599 * @hash: hash object
600 *
601 * Get the number of values in the hash.
602 *
603 * Return value: integer number of values in the hash or <0 if cannot be determined
604 **/
605 int
librdf_hash_values_count(librdf_hash * hash)606 librdf_hash_values_count(librdf_hash* hash)
607 {
608 return hash->factory->values_count(hash->context);
609 }
610
611
612 /**
613 * librdf_hash_get:
614 * @hash: hash object
615 * @key: pointer to key
616 *
617 * Retrieve one value from hash for a given key as string.
618 *
619 * The value returned is from newly allocated memory which the
620 * caller must free.
621 *
622 * Return value: the value or NULL on failure
623 **/
624 char*
librdf_hash_get(librdf_hash * hash,const char * key)625 librdf_hash_get(librdf_hash* hash, const char *key)
626 {
627 librdf_hash_datum *hd_key, *hd_value;
628 char *value=NULL;
629
630 hd_key=librdf_new_hash_datum(hash->world, (void*)key, strlen(key));
631 if(!hd_key)
632 return NULL;
633
634 hd_value=librdf_hash_get_one(hash, hd_key);
635
636 if(hd_value) {
637 if(hd_value->data) {
638 value = LIBRDF_MALLOC(char*, hd_value->size + 1);
639 if(value) {
640 /* Copy into new null terminated string for userland */
641 memcpy(value, hd_value->data, hd_value->size);
642 value[hd_value->size]='\0';
643 }
644 }
645 librdf_free_hash_datum(hd_value);
646 }
647
648 /* don't free user key */
649 hd_key->data=NULL;
650 librdf_free_hash_datum(hd_key);
651
652 return value;
653 }
654
655
656 /**
657 * librdf_hash_get_one:
658 * @hash: hash object
659 * @key: pointer to key
660 *
661 * Retrieve one value from hash for a given key.
662 *
663 * The value returned is from newly allocated memory which the
664 * caller must free.
665 *
666 * Return value: the value or NULL on failure
667 **/
668 librdf_hash_datum*
librdf_hash_get_one(librdf_hash * hash,librdf_hash_datum * key)669 librdf_hash_get_one(librdf_hash* hash, librdf_hash_datum *key)
670 {
671 librdf_hash_datum *value;
672 librdf_hash_cursor *cursor;
673 int status;
674 char *new_value;
675
676 value=librdf_new_hash_datum(hash->world, NULL, 0);
677 if(!value)
678 return NULL;
679
680 cursor=librdf_new_hash_cursor(hash);
681 if(!cursor) {
682 librdf_free_hash_datum(value);
683 return NULL;
684 }
685
686 status=librdf_hash_cursor_get_next(cursor, key, value);
687 if(!status) {
688 /* value->data will point to SHARED area, so copy it */
689 new_value = LIBRDF_MALLOC(char*, value->size);
690 if(new_value) {
691 memcpy(new_value, value->data, value->size);
692 value->data=new_value;
693 } else {
694 status=1;
695 value->data=NULL;
696 }
697 }
698
699 /* this deletes the data behind the datum */
700 librdf_free_hash_cursor(cursor);
701
702 if(status) {
703 librdf_free_hash_datum(value);
704 return NULL;
705 }
706
707 return value;
708 }
709
710
711 typedef struct {
712 librdf_hash* hash;
713 librdf_hash_cursor* cursor;
714 librdf_hash_datum *key;
715 librdf_hash_datum *value;
716
717 librdf_hash_datum next_key; /* not used if one_key set */
718 librdf_hash_datum next_value;
719 int is_end;
720 int one_key;
721 } librdf_hash_get_all_iterator_context;
722
723
724
725 /**
726 * librdf_hash_get_all:
727 * @hash: hash object
728 * @key: pointer to key
729 * @value: pointer to value
730 *
731 * Retrieve all values from hash for a given key.
732 *
733 * The iterator returns #librdf_hash_datum objects containing the values.
734 * These are newly allocated memory which the caller must free.
735 *
736 * Return value: a #librdf_iterator serialization of all values or NULL on failure
737 **/
738 librdf_iterator*
librdf_hash_get_all(librdf_hash * hash,librdf_hash_datum * key,librdf_hash_datum * value)739 librdf_hash_get_all(librdf_hash* hash,
740 librdf_hash_datum *key, librdf_hash_datum *value)
741 {
742 librdf_hash_get_all_iterator_context* context;
743 int status;
744 librdf_iterator* iterator;
745
746 context = LIBRDF_CALLOC(librdf_hash_get_all_iterator_context*, 1,
747 sizeof(*context));
748 if(!context)
749 return NULL;
750
751 if(!(context->cursor=librdf_new_hash_cursor(hash))) {
752 librdf_hash_get_all_iterator_finished(context);
753 return NULL;
754 }
755
756 if(key->data)
757 context->one_key=1;
758
759 context->hash=hash;
760 context->key=key;
761 context->value=value;
762
763 if(context->one_key)
764 status=librdf_hash_cursor_set(context->cursor, context->key,
765 &context->next_value);
766 else
767 status=librdf_hash_cursor_get_first(context->cursor, &context->next_key,
768 &context->next_value);
769
770 context->is_end=(status != 0);
771
772 iterator=librdf_new_iterator(hash->world,
773 (void*)context,
774 librdf_hash_get_all_iterator_is_end,
775 librdf_hash_get_all_iterator_next_method,
776 librdf_hash_get_all_iterator_get_method,
777 librdf_hash_get_all_iterator_finished);
778 if(!iterator)
779 librdf_hash_get_all_iterator_finished(context);
780 return iterator;
781 }
782
783
784 static int
librdf_hash_get_all_iterator_is_end(void * iterator)785 librdf_hash_get_all_iterator_is_end(void* iterator)
786 {
787 librdf_hash_get_all_iterator_context* context=(librdf_hash_get_all_iterator_context*)iterator;
788
789 return context->is_end;
790 }
791
792
793 static int
librdf_hash_get_all_iterator_next_method(void * iterator)794 librdf_hash_get_all_iterator_next_method(void* iterator)
795 {
796 librdf_hash_get_all_iterator_context* context=(librdf_hash_get_all_iterator_context*)iterator;
797 int status;
798
799 if(context->is_end)
800 return 1;
801
802 /* move on */
803
804 if(context->one_key)
805 status=librdf_hash_cursor_get_next_value(context->cursor,
806 &context->next_key,
807 &context->next_value);
808 else {
809 /* want the next key/value pair, so mark last data as used */
810 context->next_key.data=NULL;
811 status=librdf_hash_cursor_get_next(context->cursor,
812 &context->next_key,
813 &context->next_value);
814 }
815
816 if(status)
817 context->is_end=1;
818
819 return context->is_end;
820 }
821
822
823 static void*
librdf_hash_get_all_iterator_get_method(void * iterator,int flags)824 librdf_hash_get_all_iterator_get_method(void* iterator, int flags)
825 {
826 librdf_hash_get_all_iterator_context* context = (librdf_hash_get_all_iterator_context*)iterator;
827 void *result = NULL;
828
829 if(context->is_end)
830 return NULL;
831
832 switch(flags) {
833 case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
834 /* This is so that librdf_iterator_update_current_element works OK,
835 * since the get_object method isn't used for hashes,
836 * might as well return something useful to signify not-end-of-list.
837 */
838
839 result = context;
840 break;
841
842 case LIBRDF_ITERATOR_GET_METHOD_GET_KEY:
843 result = &context->next_key;
844 break;
845
846 case LIBRDF_ITERATOR_GET_METHOD_GET_VALUE:
847 result = &context->next_value;
848 break;
849
850 default:
851 librdf_log(context->hash->world,
852 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
853 "Unknown iterator method flag %d", flags);
854 result = NULL;
855 break;
856 }
857
858 return result;
859 }
860
861
862 static void
librdf_hash_get_all_iterator_finished(void * iterator)863 librdf_hash_get_all_iterator_finished(void* iterator)
864 {
865 librdf_hash_get_all_iterator_context* context=(librdf_hash_get_all_iterator_context*)iterator;
866
867 if(context->cursor)
868 librdf_free_hash_cursor(context->cursor);
869
870 if(context->key)
871 context->key->data=NULL;
872
873 if(context->value)
874 context->value->data=NULL;
875
876 LIBRDF_FREE(librdf_hash_get_all_iterator_context, context);
877 }
878
879
880 /**
881 * librdf_hash_get_del:
882 * @hash: hash object
883 * @key: pointer to key
884 *
885 * Retrieve one value from hash for a given key as string and remove all values with that key.
886 *
887 * The value returned is from newly allocated memory which the
888 * caller must free.
889 *
890 * Return value: the value or NULL on failure
891 **/
892 char*
librdf_hash_get_del(librdf_hash * hash,const char * key)893 librdf_hash_get_del(librdf_hash* hash, const char *key)
894 {
895 librdf_hash_datum hd_key;
896 char *s;
897
898 s=librdf_hash_get(hash, key);
899 if(!s)
900 return NULL;
901
902 hd_key.data=(char*)key;
903 hd_key.size=strlen(key);
904
905 librdf_hash_delete_all(hash, &hd_key);
906
907 return s;
908 }
909
910
911
912 /**
913 * librdf_hash_put:
914 * @hash: hash object
915 * @key: key
916 * @value: value
917 *
918 * Insert key/value pairs into the hash according to flags.
919 *
920 * The key and values are copied into the hash; the original pointers
921 * can be deleted.
922 *
923 * Return value: non 0 on failure
924 **/
925 int
librdf_hash_put(librdf_hash * hash,librdf_hash_datum * key,librdf_hash_datum * value)926 librdf_hash_put(librdf_hash* hash, librdf_hash_datum *key,
927 librdf_hash_datum *value)
928 {
929 return hash->factory->put(hash->context, key, value);
930 }
931
932
933 /**
934 * librdf_hash_exists:
935 * @hash: hash object
936 * @key: key
937 * @value: value
938 *
939 * Check if a given key/value is in the hash.
940 *
941 * Return value: >0 if the key/value exists in the hash, 0 if not, <0 on failure
942 **/
943 int
librdf_hash_exists(librdf_hash * hash,librdf_hash_datum * key,librdf_hash_datum * value)944 librdf_hash_exists(librdf_hash* hash, librdf_hash_datum *key,
945 librdf_hash_datum *value)
946 {
947 return hash->factory->exists(hash->context, key, value);
948 }
949
950
951 /**
952 * librdf_hash_delete:
953 * @hash: hash object
954 * @key: key
955 * @value: value
956 *
957 * Delete a key/value pair from the hash.
958 *
959 * Return value: non 0 on failure (including pair not present)
960 **/
961 int
librdf_hash_delete(librdf_hash * hash,librdf_hash_datum * key,librdf_hash_datum * value)962 librdf_hash_delete(librdf_hash* hash, librdf_hash_datum *key,
963 librdf_hash_datum *value)
964 {
965 return hash->factory->delete_key_value(hash->context, key, value);
966 }
967
968
969 /**
970 * librdf_hash_delete_all:
971 * @hash: hash object
972 * @key: key
973 *
974 * Delete a key and all values from the hash.
975 *
976 * Return value: non 0 on failure (including pair not present)
977 **/
978 int
librdf_hash_delete_all(librdf_hash * hash,librdf_hash_datum * key)979 librdf_hash_delete_all(librdf_hash* hash, librdf_hash_datum *key)
980 {
981 return hash->factory->delete_key(hash->context, key);
982 }
983
984
985 typedef struct {
986 librdf_hash* hash;
987 librdf_hash_cursor* cursor;
988 librdf_hash_datum *key;
989
990 librdf_hash_datum next_key;
991 int is_end;
992 } librdf_hash_keys_iterator_context;
993
994
995
996 /**
997 * librdf_hash_keys:
998 * @hash: hash object
999 * @key: pointer to key
1000 *
1001 * Get the hash keys.
1002 *
1003 * The iterator returns #librdf_hash_datum objects containingvalue returned is from newly allocated memory which the
1004 * caller must free.
1005 *
1006 * Return value: #librdf_iterator serialisation of keys or NULL on failure
1007 **/
1008 librdf_iterator*
librdf_hash_keys(librdf_hash * hash,librdf_hash_datum * key)1009 librdf_hash_keys(librdf_hash* hash, librdf_hash_datum *key)
1010 {
1011 librdf_hash_keys_iterator_context* context;
1012 int status;
1013 librdf_iterator* iterator;
1014
1015 context = LIBRDF_CALLOC(librdf_hash_keys_iterator_context*, 1,
1016 sizeof(*context));
1017 if(!context)
1018 return NULL;
1019
1020
1021 if(!(context->cursor=librdf_new_hash_cursor(hash))) {
1022 librdf_hash_keys_iterator_finished(context);
1023 return NULL;
1024 }
1025
1026 context->hash=hash;
1027 context->key=key;
1028
1029 status=librdf_hash_cursor_get_first(context->cursor, &context->next_key,
1030 NULL);
1031 context->is_end=(status != 0);
1032
1033 iterator=librdf_new_iterator(hash->world,
1034 (void*)context,
1035 librdf_hash_keys_iterator_is_end,
1036 librdf_hash_keys_iterator_next_method,
1037 librdf_hash_keys_iterator_get_method,
1038 librdf_hash_keys_iterator_finished);
1039 if(!iterator)
1040 librdf_hash_keys_iterator_finished(context);
1041 return iterator;
1042 }
1043
1044
1045 static int
librdf_hash_keys_iterator_is_end(void * iterator)1046 librdf_hash_keys_iterator_is_end(void* iterator)
1047 {
1048 librdf_hash_keys_iterator_context* context=(librdf_hash_keys_iterator_context*)iterator;
1049
1050 if(context->is_end)
1051 return 1;
1052
1053 /* have key */
1054 if(context->next_key.data)
1055 return 0;
1056
1057 /* no stored data, so check for it */
1058 if(librdf_hash_cursor_get_next(context->cursor, &context->next_key, NULL))
1059 context->is_end=1;
1060
1061 return context->is_end;
1062 }
1063
1064
1065 static int
librdf_hash_keys_iterator_next_method(void * iterator)1066 librdf_hash_keys_iterator_next_method(void* iterator)
1067 {
1068 librdf_hash_keys_iterator_context* context=(librdf_hash_keys_iterator_context*)iterator;
1069
1070 if(context->is_end)
1071 return 1;
1072
1073 /* move on */
1074
1075 /* want the next key, so mark last key data as used */
1076 context->next_key.data=NULL;
1077 if(librdf_hash_cursor_get_next(context->cursor, &context->next_key, NULL))
1078 context->is_end=1;
1079
1080 return context->is_end;
1081 }
1082
1083
1084 static void*
librdf_hash_keys_iterator_get_method(void * iterator,int flags)1085 librdf_hash_keys_iterator_get_method(void* iterator, int flags)
1086 {
1087 librdf_hash_keys_iterator_context* context = (librdf_hash_keys_iterator_context*)iterator;
1088 void *result = NULL;
1089
1090 if(context->is_end)
1091 return NULL;
1092
1093 switch(flags) {
1094 case LIBRDF_ITERATOR_GET_METHOD_GET_OBJECT:
1095 /* This is so that librdf_iterator_update_current_element works OK,
1096 * since the get_object method isn't used for hashes,
1097 * might as well return something useful to signify not-end-of-list.
1098 */
1099
1100 result = context;
1101 break;
1102
1103 case LIBRDF_ITERATOR_GET_METHOD_GET_KEY:
1104 result = &context->next_key;
1105 break;
1106
1107 default:
1108 result = NULL;
1109 }
1110
1111 return result;
1112 }
1113
1114
1115 static void
librdf_hash_keys_iterator_finished(void * iterator)1116 librdf_hash_keys_iterator_finished(void* iterator)
1117 {
1118 librdf_hash_keys_iterator_context* context=(librdf_hash_keys_iterator_context*)iterator;
1119
1120 if(context->cursor)
1121 librdf_free_hash_cursor(context->cursor);
1122
1123 if(context->key)
1124 context->key->data = NULL;
1125
1126 LIBRDF_FREE(librdf_hash_keys_iterator_context, context);
1127 }
1128
1129
1130 /**
1131 * librdf_hash_sync:
1132 * @hash: hash object
1133 *
1134 * Flush any cached information to disk if appropriate.
1135 *
1136 * Return value: non 0 on failure
1137 **/
1138 int
librdf_hash_sync(librdf_hash * hash)1139 librdf_hash_sync(librdf_hash* hash)
1140 {
1141 return hash->factory->sync(hash->context);
1142 }
1143
1144
1145 /**
1146 * librdf_hash_get_fd:
1147 * @hash: hash object
1148 *
1149 * Get the file descriptor for the hash.
1150 *
1151 * This returns the file descriptor if it is file based for
1152 * use with file locking.
1153 *
1154 * Return value: the file descriptor
1155 **/
1156 int
librdf_hash_get_fd(librdf_hash * hash)1157 librdf_hash_get_fd(librdf_hash* hash)
1158 {
1159 return hash->factory->get_fd(hash->context);
1160 }
1161
1162
1163 /**
1164 * librdf_hash_print:
1165 * @hash: the hash
1166 * @fh: file handle
1167 *
1168 * Pretty print the hash to a file descriptor.
1169 *
1170 **/
1171 void
librdf_hash_print(librdf_hash * hash,FILE * fh)1172 librdf_hash_print(librdf_hash* hash, FILE *fh)
1173 {
1174 librdf_iterator* iterator;
1175 librdf_hash_datum *key, *value;
1176
1177 fputs(hash->factory->name, fh);
1178 fputs(" hash: {\n", fh);
1179
1180 key = librdf_new_hash_datum(hash->world, NULL, 0);
1181 if(!key)
1182 return;
1183 value = librdf_new_hash_datum(hash->world, NULL, 0);
1184 if(!value) {
1185 librdf_free_hash_datum(key);
1186 return;
1187 }
1188
1189 iterator=librdf_hash_get_all(hash, key, value);
1190 while(!librdf_iterator_end(iterator)) {
1191 librdf_hash_datum *k, *v;
1192 size_t l;
1193
1194 k=(librdf_hash_datum *)librdf_iterator_get_key(iterator);
1195 v=(librdf_hash_datum *)librdf_iterator_get_value(iterator);
1196
1197 fputs(" '", fh);
1198 l=fwrite(k->data, 1, k->size, fh);
1199 if(l != k->size)
1200 break;
1201
1202 fputs("'=>'", fh);
1203 l=fwrite(v->data, 1, v->size, fh);
1204 if(l != v->size)
1205 break;
1206
1207 fputs("'\n", fh);
1208
1209 librdf_iterator_next(iterator);
1210 }
1211 if(iterator)
1212 librdf_free_iterator(iterator);
1213
1214 librdf_free_hash_datum(value);
1215 librdf_free_hash_datum(key);
1216
1217 fputc('}', fh);
1218 }
1219
1220
1221 /**
1222 * librdf_hash_print_keys:
1223 * @hash: the hash
1224 * @fh: file handle
1225 *
1226 * Pretty print the keys to a file descriptor.
1227 *
1228 **/
1229 void
librdf_hash_print_keys(librdf_hash * hash,FILE * fh)1230 librdf_hash_print_keys(librdf_hash* hash, FILE *fh)
1231 {
1232 librdf_iterator* iterator;
1233 librdf_hash_datum *key;
1234
1235 fputs("{\n", fh);
1236
1237 key=librdf_new_hash_datum(hash->world, NULL, 0);
1238 if(!key)
1239 return;
1240
1241 iterator=librdf_hash_keys(hash, key);
1242 while(!librdf_iterator_end(iterator)) {
1243 librdf_hash_datum *k=(librdf_hash_datum *)librdf_iterator_get_key(iterator);
1244 size_t l;
1245
1246 fputs(" '", fh);
1247 l=fwrite(k->data, 1, k->size, fh);
1248 if(l != k->size)
1249 break;
1250 fputs("'\n", fh);
1251
1252 librdf_iterator_next(iterator);
1253 }
1254 if(iterator)
1255 librdf_free_iterator(iterator);
1256
1257 librdf_free_hash_datum(key);
1258
1259 fputc('}', fh);
1260 }
1261
1262
1263 /**
1264 * librdf_hash_print_values:
1265 * @hash: the hash
1266 * @key_string: the key as a string
1267 * @fh: file handle
1268 *
1269 * Pretty print the values of one key to a file descriptor.
1270 *
1271 **/
1272 void
librdf_hash_print_values(librdf_hash * hash,const char * key_string,FILE * fh)1273 librdf_hash_print_values(librdf_hash* hash, const char *key_string, FILE *fh)
1274 {
1275 librdf_hash_datum *key, *value;
1276 librdf_iterator* iterator;
1277 int first=1;
1278
1279 key=librdf_new_hash_datum(hash->world, (char*)key_string, strlen(key_string));
1280 if(!key)
1281 return;
1282
1283 value=librdf_new_hash_datum(hash->world, NULL, 0);
1284 if(!value) {
1285 key->data=NULL;
1286 librdf_free_hash_datum(key);
1287 return;
1288 }
1289
1290 iterator=librdf_hash_get_all(hash, key, value);
1291 fputc('(', fh);
1292 while(!librdf_iterator_end(iterator)) {
1293 librdf_hash_datum *v=(librdf_hash_datum *)librdf_iterator_get_value(iterator);
1294 size_t l;
1295
1296 if(!first)
1297 fputs(", ", fh);
1298
1299 fputc('\'', fh);
1300 l=fwrite(v->data, 1, v->size, fh);
1301 if(l != v->size)
1302 break;
1303
1304 fputc('\'', fh);
1305 first=0;
1306 librdf_iterator_next(iterator);
1307 }
1308 fputc(')', fh);
1309 librdf_free_iterator(iterator);
1310
1311 key->data=NULL;
1312 librdf_free_hash_datum(key);
1313
1314 librdf_free_hash_datum(value);
1315 }
1316
1317
1318
1319 /* private enum */
1320 typedef enum {
1321 HFS_PARSE_STATE_INIT = 0,
1322 HFS_PARSE_STATE_KEY = 1,
1323 HFS_PARSE_STATE_SEP = 2,
1324 HFS_PARSE_STATE_EQ = 3,
1325 HFS_PARSE_STATE_VALUE = 4
1326 } librdf_hfs_parse_state;
1327
1328
1329 /**
1330 * librdf_hash_from_string:
1331 * @hash: hash object
1332 * @string: hash encoded as a string
1333 *
1334 * Initialise a hash from a string.
1335 *
1336 * The string format is something like:
1337 * key1='value1',key2='value2', key3='\'quoted value\''
1338 *
1339 * The 's are required and whitespace can appear around the = and ,s
1340 *
1341 * Return value: non 0 on failure
1342 **/
1343 int
librdf_hash_from_string(librdf_hash * hash,const char * string)1344 librdf_hash_from_string(librdf_hash* hash, const char *string)
1345 {
1346 const char * p;
1347 librdf_hash_datum hd_key, hd_value; /* on stack */
1348 const char *key;
1349 size_t key_len;
1350 const char *value;
1351 size_t value_len;
1352 size_t backslashes;
1353 int saw_backslash;
1354 librdf_hfs_parse_state state;
1355 size_t real_value_len;
1356 char *new_value;
1357 size_t i;
1358 char *to;
1359
1360 if(!string)
1361 return 0;
1362
1363 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
1364 LIBRDF_DEBUG2("Parsing >>%s<<\n", string);
1365 #endif
1366
1367 p=string;
1368 key=NULL; key_len=0;
1369 value=NULL;
1370 state=HFS_PARSE_STATE_INIT;
1371 while(*p) {
1372
1373 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
1374 LIBRDF_DEBUG3("state %d at %s\n", state, p);
1375 #endif
1376
1377 switch(state){
1378 /* start of config - before key */
1379 case HFS_PARSE_STATE_INIT:
1380 while(*p && (isspace((int)*p) || *p == ','))
1381 p++;
1382 if(!*p)
1383 break;
1384
1385 /* fall through to next state */
1386 state=HFS_PARSE_STATE_KEY;
1387
1388 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
1389 LIBRDF_DEBUG3("state %d at %s\n", state, p);
1390 #endif
1391
1392 /* start of key */
1393 case HFS_PARSE_STATE_KEY:
1394 key=p;
1395 while(*p && (isalnum((int)*p) || *p == '_' || *p == '-'))
1396 p++;
1397 if(!*p)
1398 break;
1399 key_len = LIBRDF_GOOD_CAST(size_t, p - key);
1400
1401 /* if 1st char is not space or alpha, move on */
1402 if(!key_len) {
1403 p++;
1404 state=HFS_PARSE_STATE_INIT;
1405 break;
1406 }
1407
1408 state=HFS_PARSE_STATE_SEP;
1409 /* fall through to next state */
1410
1411 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
1412 LIBRDF_DEBUG3("state %d at %s\n", state, p);
1413 #endif
1414
1415 /* got key, now skipping spaces */
1416 case HFS_PARSE_STATE_SEP:
1417 while(*p && isspace((int)*p))
1418 p++;
1419 if(!*p)
1420 break;
1421 /* expecting = now */
1422 if(*p != '=') {
1423 p++;
1424 state=HFS_PARSE_STATE_INIT;
1425 break;
1426 }
1427 p++;
1428 state=HFS_PARSE_STATE_EQ;
1429 /* fall through to next state */
1430
1431 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
1432 LIBRDF_DEBUG3("state %d at %s\n", state, p);
1433 #endif
1434
1435 /* got key\s+= now skipping spaces " */
1436 case HFS_PARSE_STATE_EQ:
1437 while(*p && isspace((int)*p))
1438 p++;
1439 if(!*p)
1440 break;
1441 /* expecting ' now */
1442 if(*p != '\'') {
1443 p++;
1444 state=HFS_PARSE_STATE_INIT;
1445 break;
1446 }
1447 p++;
1448 /* state=HFS_PARSE_STATE_VALUE; */
1449 /* fall through to next state */
1450
1451 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
1452 LIBRDF_DEBUG3("state %d at %s\n", state, p);
1453 #endif
1454
1455 /* got key\s+=\s+" now reading value */
1456 case HFS_PARSE_STATE_VALUE:
1457 value=p;
1458 backslashes=0;
1459 saw_backslash=0;
1460 while(*p) {
1461 if(!saw_backslash && *p == '\\') {
1462 /* backslashes are removed during value copy later */
1463 backslashes++; /* reduces real length */
1464 saw_backslash=1;
1465 } else {
1466 if (!saw_backslash && *p == '\'')
1467 break;
1468 saw_backslash=0;
1469 }
1470
1471 p++;
1472 }
1473 if(!*p)
1474 return 1;
1475
1476 /* ' at end of value found */
1477 value_len = LIBRDF_GOOD_CAST(size_t, p - value);
1478 real_value_len = value_len - backslashes;
1479 new_value = LIBRDF_MALLOC(char*, real_value_len + 1);
1480 if(!new_value)
1481 return 1;
1482
1483 for(i = 0, to = new_value; i < value_len; i++){
1484 if(value[i] == '\\')
1485 i++;
1486 *to++=value[i];
1487 }
1488 *to='\0';
1489
1490 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
1491 LIBRDF_DEBUG3("decoded key >>%s<< (true) value >>%s<<\n", key, new_value);
1492 #endif
1493
1494 hd_key.data=(void*)key; hd_key.size=key_len;
1495 hd_value.data=(void*)new_value; hd_value.size=real_value_len;
1496
1497 librdf_hash_put(hash, &hd_key, &hd_value);
1498
1499 LIBRDF_FREE(char*, new_value);
1500
1501 #if defined(LIBRDF_DEBUG) && LIBRDF_DEBUG > 1
1502 LIBRDF_DEBUG1("after decoding ");
1503 librdf_hash_print (hash, stderr) ;
1504 fputc('\n', stderr);
1505 #endif
1506 state=HFS_PARSE_STATE_INIT;
1507 p++;
1508
1509 break;
1510
1511 default:
1512 librdf_log(hash->world,
1513 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
1514 "No such state %d", state);
1515 return 1;
1516 }
1517 }
1518 return 0;
1519 }
1520
1521
1522 /**
1523 * librdf_hash_from_array_of_strings:
1524 * @hash: hash object
1525 * @array: address of the start of the array of char* pointers
1526 *
1527 * Initialise a hash from an array of strings.
1528 *
1529 * Return value: non 0 on failure
1530 **/
1531 int
librdf_hash_from_array_of_strings(librdf_hash * hash,const char ** array)1532 librdf_hash_from_array_of_strings(librdf_hash* hash, const char **array)
1533 {
1534 librdf_hash_datum key, value; /* on stack */
1535 int i;
1536
1537 for(i=0; (key.data=(char*)array[i]); i+=2) {
1538 value.data=(char*)array[i+1];
1539 if(!value.data) {
1540 librdf_log(hash->world,
1541 0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
1542 "Array contains an odd number of strings - %d", i);
1543 return 1;
1544 }
1545 key.size=strlen((char*)key.data);
1546 value.size=strlen((char*)value.data);
1547 librdf_hash_put(hash, &key, &value);
1548 }
1549 return 0;
1550 }
1551
1552
1553 /**
1554 * librdf_hash_to_string:
1555 * @hash: #librdf_hash object
1556 * @filter: NULL terminated list of keys to ignore
1557 *
1558 * Format the hash as a string, suitable for parsing by librdf_hash_from_string.
1559 *
1560 * Note: this method allocates a new string since this is a _to_ method
1561 * and the caller must call librdf_free_memory() to free the resulting memory.
1562 *
1563 * Return value: string representation of the hash or NULL on failure
1564 **/
1565 char*
librdf_hash_to_string(librdf_hash * hash,const char * filter[])1566 librdf_hash_to_string(librdf_hash* hash, const char *filter[])
1567 {
1568 librdf_hash_datum *key = NULL, *value = NULL;
1569 librdf_iterator* iterator = NULL;
1570 raptor_stringbuffer* sb;
1571 char* result = NULL;
1572 size_t len;
1573
1574 LIBRDF_ASSERT_OBJECT_POINTER_RETURN_VALUE(hash, librdf_hash, NULL);
1575
1576 sb = raptor_new_stringbuffer();
1577 if(!sb)
1578 goto tidy;
1579
1580 key=librdf_new_hash_datum(hash->world, NULL, 0);
1581 value=librdf_new_hash_datum(hash->world, NULL, 0);
1582 if (!key || !value)
1583 goto tidy;
1584
1585 iterator=librdf_hash_get_all(hash, key, value);
1586 if (!iterator)
1587 goto tidy;
1588
1589 while(!librdf_iterator_end(iterator)) {
1590 librdf_hash_datum *k, *v;
1591 int key_is_filtered = 0;
1592 size_t i;
1593
1594 k=(librdf_hash_datum *)librdf_iterator_get_key(iterator);
1595 v=(librdf_hash_datum *)librdf_iterator_get_value(iterator);
1596 if (!k || !v)
1597 break;
1598
1599 /* Is this one of the keys that we are ignoring? */
1600 if(filter) {
1601 for(i=0; filter[i]; i++) {
1602 size_t f_len = strlen(filter[i]);
1603 if(f_len == k->size &&
1604 strncmp((const char*)k->data, filter[i], f_len) == 0) {
1605 key_is_filtered = 1;
1606 break;
1607 }
1608 }
1609 }
1610
1611 if(!key_is_filtered) {
1612 if(raptor_stringbuffer_length(sb) > 0)
1613 raptor_stringbuffer_append_counted_string(sb, (unsigned char*)", ", 2, 1);
1614
1615 raptor_stringbuffer_append_counted_string(sb, (unsigned char*)k->data, k->size, 1);
1616 raptor_stringbuffer_append_counted_string(sb, (unsigned char*)"='", 2, 1);
1617
1618 for(i=0; i < v->size; i++) {
1619 char c = ((char*)v->data)[i];
1620 switch (c) {
1621 case '\'':
1622 raptor_stringbuffer_append_counted_string(sb, (unsigned char*)"\\'", 2, 1);
1623 break;
1624 case '\\':
1625 raptor_stringbuffer_append_counted_string(sb, (unsigned char*)"\\\\", 2, 1);
1626 break;
1627 default:
1628 raptor_stringbuffer_append_counted_string(sb, (unsigned char*)&c, 1, 1);
1629 break;
1630 }
1631 }
1632
1633 raptor_stringbuffer_append_counted_string(sb, (unsigned char*)"'", 1, 1);
1634 }
1635
1636 librdf_iterator_next(iterator);
1637 }
1638
1639 /* Generate a string result */
1640 len=raptor_stringbuffer_length(sb);
1641 result = (char *)librdf_alloc_memory(len + 1);
1642 if (result)
1643 raptor_stringbuffer_copy_to_string(sb, (unsigned char*)result, len);
1644
1645
1646 tidy:
1647 if(iterator)
1648 librdf_free_iterator(iterator);
1649 if(value)
1650 librdf_free_hash_datum(value);
1651 if(key)
1652 librdf_free_hash_datum(key);
1653 if(sb)
1654 raptor_free_stringbuffer(sb);
1655
1656 return result;
1657 }
1658
1659
1660 /**
1661 * librdf_hash_get_as_boolean:
1662 * @hash: #librdf_hash object
1663 * @key: key string to look up
1664 *
1665 * Lookup a hash key and decode value as a boolean.
1666 *
1667 * False values: "no", "false"
1668 * True values: "yes", "true"
1669 *
1670 * Return value: >0 (for true), 0 (for false) or <0 (for key not found or not known boolean value)
1671 **/
1672 int
librdf_hash_get_as_boolean(librdf_hash * hash,const char * key)1673 librdf_hash_get_as_boolean(librdf_hash* hash, const char *key)
1674 {
1675 int bvalue = (-1);
1676 char *value;
1677
1678 value = librdf_hash_get(hash, key);
1679 if(!value)
1680 /* does not exist - fail */
1681 return -1;
1682
1683 switch(strlen(value)) {
1684 case 2: /* try 'no' */
1685 if(*value == 'n' && value[1] == 'o')
1686 bvalue = 0;
1687 break;
1688
1689 case 3: /* try 'yes' */
1690 if(*value == 'y' && value[1] == 'e' && value[2] == 's')
1691 bvalue = 1;
1692 break;
1693
1694 case 4: /* try 'true' */
1695 if(*value == 't' && value[1] == 'r' && value[2] == 'u' && value[3] == 'e')
1696 bvalue = 1;
1697 break;
1698
1699 case 5: /* try 'false' */
1700 if(!strncmp(value, "false", 5))
1701 bvalue = 0;
1702 break;
1703 /* no need for default, bvalue is set above */
1704 }
1705
1706 LIBRDF_FREE(char*, value);
1707
1708 return bvalue;
1709 }
1710
1711
1712 /**
1713 * librdf_hash_get_as_long:
1714 * @hash: #librdf_hash object
1715 * @key: key string to look up
1716 *
1717 * Lookup a hash key and decode value as a long.
1718 *
1719 * Return value: >0 (for success), <0 (for key not found or not known boolean value)
1720 **/
1721 long
librdf_hash_get_as_long(librdf_hash * hash,const char * key)1722 librdf_hash_get_as_long(librdf_hash* hash, const char *key)
1723 {
1724 long lvalue;
1725 char *value;
1726 char *end_ptr;
1727
1728 value = librdf_hash_get(hash, key);
1729 if(!value)
1730 /* does not exist - fail */
1731 return -1;
1732
1733 /* Using special base 0 which allows decimal, hex and octal */
1734 lvalue = strtol(value, &end_ptr, 0);
1735
1736 /* nothing found, return error */
1737 if(end_ptr == value)
1738 lvalue= (-1);
1739
1740 LIBRDF_FREE(char*, value);
1741 return lvalue;
1742 }
1743
1744
1745 /**
1746 * librdf_hash_put_strings:
1747 * @hash: hash object
1748 * @key: key
1749 * @value: value
1750 *
1751 * Insert key/value pairs into the hash as strings.
1752 *
1753 * The key and values are copied into the hash, no sharing i s done.
1754 *
1755 * Return value: non 0 on failure
1756 **/
1757 int
librdf_hash_put_strings(librdf_hash * hash,const char * key,const char * value)1758 librdf_hash_put_strings(librdf_hash* hash, const char *key, const char *value)
1759 {
1760 librdf_hash_datum key_hd; /* static */
1761 librdf_hash_datum value_hd;
1762
1763 /* Note: We do not have to init the world field of
1764 * these librdf_hash_datum since they are never put on the
1765 * hash datums free list
1766 */
1767
1768 key_hd.data=(void*)key;
1769 key_hd.size=strlen(key);
1770 value_hd.data=(void*)value;
1771 value_hd.size=strlen(value);
1772 return librdf_hash_put(hash, &key_hd, &value_hd);
1773 }
1774
1775
1776 /**
1777 * librdf_hash_interpret_template:
1778 * @template_string: template string to interprate
1779 * @dictionary: dictionary of key/values to substitute
1780 * @prefix: prefix to mark a key in the template
1781 * @suffix: suffix to mark a key in the template
1782 *
1783 * Interpret keys in a template string to their value in a dictionary.
1784 *
1785 * Can be used to do variable substitution for a string where
1786 * the syntax that marks the variable is defined by the @prefix
1787 * and @suffix strings, and the variables are stored in the @dictionary
1788 * hash table.
1789 *
1790 * Return value: Newly allocated string, or NULL on failure
1791 **/
1792 unsigned char*
librdf_hash_interpret_template(const unsigned char * template_string,librdf_hash * dictionary,const unsigned char * prefix,const unsigned char * suffix)1793 librdf_hash_interpret_template(const unsigned char* template_string,
1794 librdf_hash* dictionary,
1795 const unsigned char* prefix,
1796 const unsigned char* suffix)
1797 {
1798 raptor_stringbuffer* sb;
1799 unsigned char* result=NULL;
1800 size_t len;
1801 size_t prefix_len=strlen((const char*)prefix);
1802 size_t suffix_len=strlen((const char*)suffix);
1803
1804 sb=raptor_new_stringbuffer();
1805 if(!sb)
1806 return NULL;
1807
1808 len=strlen((const char*)template_string);
1809
1810 while(*template_string) {
1811 unsigned char* p;
1812 unsigned char* s;
1813 librdf_hash_datum key; /* static */
1814 librdf_hash_datum *hd_value;
1815 size_t len2;
1816
1817 p=(unsigned char*)strstr((const char*)template_string, (const char*)prefix);
1818 if(!p) {
1819 /* No more prefixes found so append rest of template */
1820 raptor_stringbuffer_append_counted_string(sb, template_string, len, 1);
1821 break;
1822 }
1823 len2 = LIBRDF_GOOD_CAST(size_t, p - template_string);
1824 if(len2)
1825 raptor_stringbuffer_append_counted_string(sb, template_string, len2, 1);
1826
1827 template_string += len2 + prefix_len; len -= len2 + prefix_len;
1828
1829 /* key starts here */
1830 key.data=(void*)template_string;
1831
1832 s=(unsigned char*)strstr((const char*)template_string, (const char*)suffix);
1833 if(!s)
1834 /* template ended without a closing key suffix so just give up */
1835 break;
1836
1837 /* now have key */
1838 len2 = LIBRDF_GOOD_CAST(size_t, s - (unsigned char*)key.data);
1839 key.size= len2;
1840
1841 /* move past key and suffix */
1842 template_string += len2 + suffix_len; len -= len2 + suffix_len;
1843
1844 hd_value=librdf_hash_get_one(dictionary, &key);
1845 /* append value if there is one */
1846 if(hd_value) {
1847 raptor_stringbuffer_append_counted_string(sb,
1848 (const unsigned char*)hd_value->data,
1849 hd_value->size, 1);
1850 librdf_free_hash_datum(hd_value);
1851 }
1852
1853 }
1854
1855 /* Generate a string result */
1856 len=raptor_stringbuffer_length(sb);
1857 if(len) {
1858 result = LIBRDF_MALLOC(unsigned char*, len + 1);
1859 raptor_stringbuffer_copy_to_string(sb, result, len);
1860 }
1861
1862 raptor_free_stringbuffer(sb);
1863 return result;
1864 }
1865
1866
1867
1868
1869 #endif
1870
1871
1872 /* TEST CODE */
1873
1874
1875 #ifdef STANDALONE
1876
1877 /* one more prototype */
1878 int main(int argc, char *argv[]);
1879
1880
1881 int
main(int argc,char * argv[])1882 main(int argc, char *argv[])
1883 {
1884 librdf_hash *h, *h2, *ch;
1885 const char *test_hash_types[]={"bdb", "memory", NULL};
1886 const char *test_hash_values[]={"colour","yellow", /* Made in UK, can you guess? */
1887 "age", "new",
1888 "size", "large",
1889 "colour", "green",
1890 "fruit", "banana",
1891 "colour", "yellow",
1892 NULL, NULL};
1893 const char *test_duplicate_key="colour";
1894 const char *test_hash_array[]={"shape", "cube",
1895 "sides", "6", /* for testing get as long */
1896 "3d", "yes", /* testing bool */
1897 "colours", "red",
1898 "colours", "yellow",
1899 "creator", "rubik",
1900 NULL};
1901 const char * const test_hash_string="field1='value1', field2='\\'value2', field3='\\\\', field4='\\\\\\'', field5 = 'a' ";
1902 const char *test_hash_delete_key="size";
1903 const unsigned char* template_string=(const unsigned char*)"the shape is %{shape} and the sides are %{sides} created by %{rubik}";
1904 const unsigned char* template_expected=(const unsigned char*)"the shape is cube and the sides are 6 created by ";
1905 const char * filter_string[] = {"field1", NULL};
1906 int i,j;
1907 const char *type;
1908 librdf_hash_datum hd_key, hd_value; /* on stack */
1909 const char *program=librdf_basename((const char*)argv[0]);
1910 int b;
1911 long l;
1912 char* string_result;
1913 unsigned char* template_result;
1914 librdf_world *world;
1915
1916 world=librdf_new_world();
1917 librdf_world_open(world);
1918
1919 if(argc ==2) {
1920 type=argv[1];
1921 h=librdf_new_hash(world, NULL);
1922 if(!h) {
1923 fprintf(stderr, "%s: Failed to create new hash type '%s'\n",
1924 program, type);
1925 return(0);
1926 }
1927
1928 librdf_hash_open(h, "test", 0644, 1, 1, NULL);
1929 librdf_hash_from_string(h, argv[1]);
1930 fprintf(stdout, "%s: resulting ", program);
1931 librdf_hash_print(h, stdout);
1932 fputc('\n', stdout);
1933 fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h));
1934 librdf_hash_close(h);
1935 librdf_free_hash(h);
1936 return(0);
1937 }
1938
1939
1940 for(i=0; (type=test_hash_types[i]); i++) {
1941 fprintf(stdout, "%s: Trying to create new %s hash\n", program, type);
1942 h=librdf_new_hash(world, type);
1943 if(!h) {
1944 fprintf(stderr, "%s: Failed to create new hash type '%s'\n", program, type);
1945 continue;
1946 }
1947
1948 if(librdf_hash_open(h, "test", 0644, 1, 1, NULL)) {
1949 fprintf(stderr, "%s: Failed to open new hash type '%s'\n", program, type);
1950 continue;
1951 }
1952
1953
1954 for(j=0; test_hash_values[j]; j+=2) {
1955 hd_key.data=(char*)test_hash_values[j];
1956 hd_value.data=(char*)test_hash_values[j+1];
1957 fprintf(stdout, "%s: Adding key/value pair: %s=%s\n", program,
1958 (char*)hd_key.data, (char*)hd_value.data);
1959
1960 hd_key.size=strlen((char*)hd_key.data);
1961 hd_value.size=strlen((char*)hd_value.data);
1962 librdf_hash_put(h, &hd_key, &hd_value);
1963
1964 fprintf(stdout, "%s: resulting ", program);
1965 librdf_hash_print(h, stdout);
1966 fputc('\n', stdout);
1967 fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h));
1968 }
1969
1970 fprintf(stdout, "%s: Deleting key '%s'\n", program, test_hash_delete_key);
1971 hd_key.data=(char*)test_hash_delete_key;
1972 hd_key.size=strlen((char*)hd_key.data);
1973 librdf_hash_delete_all(h, &hd_key);
1974
1975 fprintf(stdout, "%s: resulting ", program);
1976 librdf_hash_print(h, stdout);
1977 fputc('\n', stdout);
1978 fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h));
1979
1980 fprintf(stdout, "%s: resulting %s hash keys: ", program, type);
1981 librdf_hash_print_keys(h, stdout);
1982 fputc('\n', stdout);
1983
1984 fprintf(stdout, "%s: all values of key '%s'=", program, test_duplicate_key);
1985 librdf_hash_print_values(h, test_duplicate_key, stdout);
1986 fputc('\n', stdout);
1987
1988 fprintf(stdout, "%s: cloning %s hash\n", program, type);
1989 ch=librdf_new_hash_from_hash(h);
1990 if(ch) {
1991 fprintf(stdout, "%s: resulting cloned ", program);
1992 librdf_hash_print(ch, stdout);
1993 fputc('\n', stdout);
1994 fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(ch));
1995
1996 librdf_hash_close(ch);
1997 librdf_free_hash(ch);
1998 } else {
1999 fprintf(stderr, "%s: Failed to clone %s hash\n", program, type);
2000 }
2001
2002 librdf_hash_close(h);
2003
2004 fprintf(stdout, "%s: Freeing hash\n", program);
2005 librdf_free_hash(h);
2006 }
2007 fprintf(stdout, "%s: Getting default hash factory\n", program);
2008 h2=librdf_new_hash(world, NULL);
2009 if(!h2) {
2010 fprintf(stderr, "%s: Failed to create new hash from default factory\n", program);
2011 return(1);
2012 }
2013
2014 fprintf(stdout, "%s: Initialising hash from array of strings\n", program);
2015 if(librdf_hash_from_array_of_strings(h2, test_hash_array)) {
2016 fprintf(stderr, "%s: Failed to init hash from array of strings\n", program);
2017 return(1);
2018 }
2019
2020 fprintf(stdout, "%s: resulting hash ", program);
2021 librdf_hash_print(h2, stdout);
2022 fputc('\n', stdout);
2023 fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h2));
2024
2025 fprintf(stdout, "%s: resulting hash keys: ", program);
2026 librdf_hash_print_keys(h2, stdout);
2027 fputc('\n', stdout);
2028
2029
2030 /* test get as boolean and long functions */
2031 {
2032 librdf_iterator* iterator;
2033 librdf_hash_datum *key_hd;
2034
2035 key_hd=librdf_new_hash_datum(world, NULL, 0);
2036
2037 iterator=librdf_hash_keys(h2, key_hd);
2038 while(!librdf_iterator_end(iterator)) {
2039 librdf_hash_datum *k=(librdf_hash_datum*)librdf_iterator_get_key(iterator);
2040 char *key_string;
2041
2042 key_string = LIBRDF_MALLOC(char*, k->size + 1);
2043 if(!key_string)
2044 break;
2045 strncpy(key_string, (char*)k->data, k->size);
2046 key_string[k->size]='\0';
2047
2048 fprintf(stdout, "%s: boolean value of key '%s' is ", program,
2049 key_string);
2050 b=librdf_hash_get_as_boolean(h2, key_string);
2051 fprintf(stdout, "%d (0 F, -1 Bad, else T)\n", b);
2052
2053 fprintf(stdout, "%s: long value of key '%s' is ", program,
2054 key_string);
2055 l=librdf_hash_get_as_long(h2, key_string);
2056 fprintf(stdout, "%ld (decimal, -1 Bad)\n", l);
2057
2058 LIBRDF_FREE(char*, key_string);
2059 librdf_iterator_next(iterator);
2060 }
2061 if(iterator)
2062 librdf_free_iterator(iterator);
2063
2064 librdf_free_hash_datum(key_hd);
2065 }
2066
2067 fprintf(stdout, "%s: Freeing hash\n", program);
2068 /* close() done automatically by free so not required */
2069 /* librdf_hash_close(h2); */
2070 librdf_free_hash(h2);
2071
2072
2073 h2=librdf_new_hash(world, NULL);
2074 fprintf(stdout, "%s: Initialising hash from string >>%s<<\n", program,
2075 test_hash_string);
2076 librdf_hash_from_string (h2, test_hash_string);
2077 fprintf(stdout, "%s: resulting ", program);
2078 librdf_hash_print(h2, stdout);
2079 fputc('\n', stdout);
2080 fprintf(stdout, "%s: values count %d\n", program, librdf_hash_values_count(h2));
2081
2082 fprintf(stdout, "%s: Converting hash back to a string\n", program);
2083 string_result=librdf_hash_to_string(h2, NULL);
2084
2085 /* Order is not guaranteed, so sadly we can't just do a full string comparison */
2086 if(!strstr(string_result, "field1='value1'")) {
2087 fprintf(stdout, "%s: Did not see field1='value1' in the generated string >>%s<<\n",
2088 program, string_result);
2089 exit(1);
2090 } else if(!strstr(string_result, "field2='\\'value2'")) {
2091 fprintf(stdout, "%s: Did not see field2='\\'value2'' in the generated string >>%s<<\n",
2092 program, string_result);
2093 exit(1);
2094 } else if(!strstr(string_result, "field3='\\\\'")) {
2095 fprintf(stdout, "%s: Did not see field3='\\\\' in the generated string >>%s<<\n",
2096 program, string_result);
2097 exit(1);
2098 } else if(!strstr(string_result, "field4='\\\\\\'")) {
2099 fprintf(stdout, "%s: Did not see field4='\\\\\\' in the generated string >>%s<<\n",
2100 program, string_result);
2101 exit(1);
2102 } else if(!strstr(string_result, "field5='a'")) {
2103 fprintf(stdout, "%s: Did not see field5='a' in the generated string >>%s<<\n",
2104 program, string_result);
2105 exit(1);
2106 } else {
2107 fprintf(stdout, "%s: resulting in >>%s<<\n", program, string_result);
2108 }
2109 librdf_free_memory(string_result);
2110
2111 fprintf(stdout, "%s: Converting hash back to a string with filter\n", program);
2112 string_result=librdf_hash_to_string(h2, filter_string);
2113 if(strstr(string_result, "field1")) {
2114 fprintf(stdout, "%s: Was not expecting >>field1<< to be in the generated string >>%s<<\n",
2115 program, string_result);
2116 exit(1);
2117 } else {
2118 fprintf(stdout, "%s: resulting in >>%s<<\n", program, string_result);
2119 }
2120 librdf_free_memory(string_result);
2121
2122 librdf_free_hash(h2);
2123
2124
2125
2126 fprintf(stdout, "%s: Subtituting into template >>%s<<\n", program,
2127 template_string);
2128 h2=librdf_new_hash(world, NULL);
2129 librdf_hash_from_array_of_strings(h2, test_hash_array);
2130
2131 template_result=librdf_hash_interpret_template(template_string, h2,
2132 (const unsigned char*)"%{",
2133 (const unsigned char*)"}");
2134 if(strcmp((const char*)template_result, (const char*)template_expected)) {
2135 fprintf(stdout, "%s: Templating failed. Result was >>%s<< but expected >>%s<<\n", program,
2136 template_result, template_expected);
2137 exit(1);
2138 } else
2139 fprintf(stdout, "%s: resulting in >>%s<<\n", program, template_result);
2140
2141 LIBRDF_FREE(char*, template_result);
2142
2143 librdf_free_hash(h2);
2144
2145
2146 librdf_free_world(world);
2147
2148 /* keep gcc -Wall happy */
2149 return(0);
2150 }
2151
2152 #endif
2153