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