LTP GCOV extension - code coverage report
Current view: directory - src/base - pdf-hash.c
Test: libgnupdf.info
Date: 2010-07-31 Instrumented lines: 148
Code covered: 84.5 % Executed lines: 125

       1                 : /* -*- mode: C -*-
       2                 :  *
       3                 :  *       File:         pdf-hash.c
       4                 :  *       Date:         Sat Apr  12 12:22:05 2008
       5                 :  *
       6                 :  *       GNU PDF Library - Implementation file for the Hash module
       7                 :  *
       8                 :  */
       9                 : 
      10                 : /* Copyright (C) 2008 Free Software Foundation, Inc. */
      11                 : 
      12                 : /* This program is free software: you can redistribute it and/or modify
      13                 :  * it under the terms of the GNU General Public License as published by
      14                 :  * the Free Software Foundation, either version 3 of the License, or
      15                 :  * (at your option) any later version.
      16                 :  *
      17                 :  * This program is distributed in the hope that it will be useful,
      18                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20                 :  * GNU General Public License for more details.
      21                 :  *
      22                 :  * You should have received a copy of the GNU General Public License
      23                 :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24                 :  */
      25                 : 
      26                 : #include <config.h>
      27                 : 
      28                 : #include <limits.h>
      29                 : #include <stdio.h>
      30                 : #include <stdlib.h>
      31                 : #include <string.h>
      32                 : 
      33                 : #include <pdf-global.h>
      34                 : #include <pdf-error.h>
      35                 : #include <pdf-alloc.h>
      36                 : #include <gl_array_list.h>
      37                 : #include <gl_linkedhash_list.h>
      38                 : 
      39                 : #include <pdf-hash.h>
      40                 : 
      41                 : #define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
      42                 : 
      43                 : /* Compute a hash code for a NUL-terminated string starting at X,
      44                 :    and return the hash code.
      45                 :    The result is platform dependent: it depends on the size of the 'size_t'
      46                 :    type and on the signedness of the 'char' type.  */
      47                 : static size_t hash_pjw (const void *x);
      48                 : 
      49                 : /* Returns true if both element string keys are equal */
      50                 : static bool elem_key_equal (const void *elt1, const void *elt2);
      51                 : 
      52                 : /* Returns true if both string keys are equal */
      53                 : static bool key_equal (const void *key1, const void *key2);
      54                 : 
      55                 : /* Returns 1 if str is only composed by numbers, 0 otherwise. */
      56                 : static int key_numeric_p (const char *str);
      57                 : 
      58                 : /* Returns <0,=0,>0 if key1 is <,==, or > than key2 */
      59                 : static int key_numeric_cmp (const char *key1, const char *key2);
      60                 : 
      61                 : /* Returns <0,=0,>0 if key1 is <,==, or > than key2 */
      62                 : static int key_compare (const void *key1, const void *key2);
      63                 : 
      64                 : pdf_status_t
      65                 : pdf_hash_new (pdf_hash_key_dispose_fn_t dispose_key_fn, pdf_hash_t *table)
      66             886 : {
      67                 :   pdf_status_t st;
      68                 : 
      69             886 :   st = PDF_OK;
      70                 : 
      71             886 :   if (table != NULL)
      72                 :     {
      73             885 :       table->elements = gl_list_nx_create_empty (GL_LINKEDHASH_LIST,
      74                 :                                                  elem_key_equal, hash_pjw,
      75                 :                                                  NULL, 0);
      76                 : 
      77             885 :       if (table->elements != NULL)
      78                 :         {
      79             885 :           table->keys = gl_list_nx_create_empty (GL_ARRAY_LIST, key_equal, NULL,
      80                 :                                                  dispose_key_fn, 0);
      81                 : 
      82             885 :           if (table->keys == NULL)
      83                 :             {
      84               0 :               st = PDF_ENOMEM;
      85                 :             }
      86                 :         }
      87                 :       else
      88                 :         {
      89               0 :           st = PDF_ENOMEM;
      90                 :         }
      91                 :     }
      92                 :   else
      93                 :     {
      94               1 :       st = PDF_EBADDATA;
      95                 :     }
      96                 : 
      97             886 :   return st;
      98                 : }
      99                 : 
     100                 : 
     101                 : pdf_status_t
     102                 : pdf_hash_destroy (pdf_hash_t table)
     103              82 : {
     104                 :   gl_list_iterator_t itr;
     105                 :   const void *elt;
     106                 : 
     107              82 :   if (table.elements != NULL && table.keys != NULL)
     108                 :     {
     109             164 :       itr = gl_list_iterator ((gl_list_t)table.elements);
     110             204 :       while (gl_list_iterator_next (&itr, &elt, NULL))
     111                 :         {
     112              40 :           if (((pdf_hash_element_t*)elt)->disp_fn != NULL)
     113                 :             {
     114               5 :               ((pdf_hash_element_t*)elt)->
     115                 :                 disp_fn ((void*) ((pdf_hash_element_t*)elt)->value);
     116                 :             }
     117              40 :           pdf_dealloc((pdf_hash_element_t*)elt);
     118                 :         }
     119                 :       gl_list_iterator_free (&itr);
     120                 :   
     121              82 :       gl_list_free((gl_list_t)table.elements);
     122              82 :       gl_list_free((gl_list_t)table.keys);
     123                 :     }
     124                 :   
     125              82 :   return PDF_OK;
     126                 : }
     127                 : 
     128                 : 
     129                 : pdf_size_t
     130                 : pdf_hash_size (const pdf_hash_t table)
     131               1 : {
     132               2 :   return (gl_list_size ((gl_list_t) table.keys));
     133                 : }
     134                 : 
     135                 : 
     136                 : pdf_bool_t
     137                 : pdf_hash_key_p (const pdf_hash_t table, const char *key)
     138              16 : {
     139              32 :   if (gl_sortedlist_search ((gl_list_t) table.keys, key_compare,
     140                 :                       (const void*) key) != NULL)
     141                 :     {
     142              12 :       return PDF_TRUE;
     143                 :     }
     144                 :   
     145               4 :   return PDF_FALSE;
     146                 : }
     147                 : 
     148                 : 
     149                 : pdf_status_t
     150                 : pdf_hash_rename (pdf_hash_t table, const char *key, const char *new_key)
     151               4 : {
     152                 :   pdf_status_t st;
     153                 :   gl_list_node_t knode, vnode, tnode;
     154                 :   pdf_hash_element_t elem, *updated;
     155                 :   
     156               4 :   st = PDF_OK;
     157                 : 
     158               4 :   if (key != NULL && new_key != NULL)
     159                 :     {
     160               4 :       knode = gl_sortedlist_search ((gl_list_t) table.keys, key_compare, key);
     161               2 :       if (knode != NULL)
     162                 :         {
     163                 :           /* get the node from key and update its key*/
     164               1 :           elem.key = key;
     165               1 :           vnode = gl_list_search ((gl_list_t)table.elements, &elem);
     166               2 :           updated = (pdf_hash_element_t*)
     167                 :             gl_list_node_value ((gl_list_t)table.elements, vnode);
     168               1 :           updated->key = new_key;
     169                 : 
     170                 :           /* update the lists */
     171               2 :           tnode = gl_list_nx_add_first ((gl_list_t) table.elements, updated);
     172               1 :           if (tnode != NULL)
     173                 :             {
     174               1 :               gl_list_remove_node ((gl_list_t)table.elements, vnode);
     175                 :           
     176               2 :               if (gl_sortedlist_nx_add ((gl_list_t)table.keys, key_compare, new_key)
     177                 :                   != NULL)
     178                 :                 {
     179               1 :                   gl_sortedlist_remove ((gl_list_t)table.keys, key_compare, key);
     180                 :                 }
     181                 :               else
     182                 :                 {
     183               0 :                   gl_list_remove_node ((gl_list_t) table.elements, tnode);
     184               0 :                   st = PDF_ENOMEM;
     185                 :                 }
     186                 :             }
     187                 :           else
     188                 :             {
     189               0 :               st = PDF_ENOMEM;
     190                 :             }
     191                 :         }
     192                 :       else
     193                 :         {
     194               1 :           st = PDF_ERROR;
     195                 :         }
     196                 :     }
     197                 :   else
     198                 :     {
     199               2 :       st = PDF_EBADDATA;
     200                 :     }
     201                 : 
     202               4 :   return st;
     203                 : 
     204                 : }
     205                 : 
     206                 : 
     207                 : pdf_status_t
     208                 : pdf_hash_add (pdf_hash_t table, const char *key, const void *element,
     209                 :               pdf_hash_element_dispose_fn_t disp_fn)
     210              43 : {
     211                 :   pdf_status_t st;
     212                 :   pdf_hash_element_t *newelt;
     213                 :   gl_list_node_t tnode;
     214              43 :   st = PDF_OK;
     215                 : 
     216              43 :   if (key != NULL && element != NULL)
     217                 :     {
     218              41 :       newelt = pdf_alloc (sizeof (pdf_hash_element_t));
     219              41 :       if (newelt != NULL)
     220                 :         {
     221              41 :           newelt->key = key;
     222              41 :           newelt->value = element;
     223              41 :           newelt->disp_fn = disp_fn;
     224              82 :           tnode = gl_list_nx_add_first ((gl_list_t) table.elements, newelt);
     225              41 :           if (tnode != NULL)
     226                 :             {
     227              82 :               if (gl_sortedlist_nx_add ((gl_list_t) table.keys, key_compare, key)
     228                 :                   == NULL)
     229                 :                 {
     230               0 :                   gl_list_remove_node ((gl_list_t) table.elements, tnode);
     231               0 :                   st = PDF_ENOMEM;
     232                 :                 }
     233                 :             }
     234                 :           else
     235                 :             {
     236               0 :               pdf_dealloc (newelt);
     237               0 :               st = PDF_ENOMEM;
     238                 :             }
     239                 :         }
     240                 :       else
     241                 :         {
     242               0 :           st = PDF_ENOMEM;
     243                 :         }
     244                 :     }
     245                 :   else
     246                 :     {
     247               2 :       st = PDF_EBADDATA;
     248                 :     }
     249                 :   
     250                 : 
     251              43 :   return st;
     252                 : 
     253                 : }
     254                 : 
     255                 : 
     256                 : pdf_status_t
     257                 : pdf_hash_remove (pdf_hash_t table, const char *key)
     258               3 : {
     259                 :   pdf_status_t st;
     260                 :   pdf_hash_element_t elt;
     261                 :   gl_list_node_t node;
     262                 :   
     263               3 :   st = PDF_OK;
     264                 : 
     265               3 :   if (key != NULL)
     266                 :     {
     267               2 :       elt.key = key;
     268               2 :       node = gl_list_search ((gl_list_t)table.elements, &elt);
     269               2 :       if (node != NULL)
     270                 :         {
     271                 :           pdf_hash_element_t *removed;
     272               2 :           removed = (pdf_hash_element_t*)
     273                 :                     gl_list_node_value((gl_list_t)table.elements, node);
     274                 : 
     275               1 :           if (removed->disp_fn != NULL)
     276                 :             {
     277               0 :               removed->disp_fn (removed->value);
     278                 :             }
     279                 : 
     280               1 :           pdf_dealloc(removed);
     281               1 :           gl_list_remove_node ((gl_list_t)table.elements, node);
     282               1 :           gl_sortedlist_remove ((gl_list_t)table.keys, key_compare, key);
     283                 :         }
     284                 :       else
     285                 :         {
     286               1 :           st = PDF_ERROR;
     287                 :         }
     288                 :     }
     289                 :   else
     290                 :     {
     291               1 :       st = PDF_EBADDATA;
     292                 :     }
     293                 :   
     294                 : 
     295               3 :   return st;
     296                 : 
     297                 : }
     298                 : 
     299                 : 
     300                 : pdf_status_t
     301                 : pdf_hash_get (const pdf_hash_t table, const char *key, const void **elem_pointer)
     302              14 : {
     303                 :   pdf_status_t st;
     304                 :   gl_list_node_t node;
     305                 :   pdf_hash_element_t elem, *searched;
     306                 : 
     307              14 :   st = PDF_OK;
     308                 : 
     309              14 :   if (key != NULL && elem_pointer != NULL)
     310                 :     {
     311              12 :       elem.key = key;
     312              12 :       node = gl_list_search ((gl_list_t)table.elements, &elem);
     313              12 :       if (node != NULL)
     314                 :         {
     315              22 :           searched = (pdf_hash_element_t*)
     316                 :             gl_list_node_value ((gl_list_t)table.elements, node);
     317              11 :           *elem_pointer = searched->value;
     318                 :         }
     319                 :       else
     320                 :         {
     321               1 :           st = PDF_ERROR;
     322                 :         }
     323                 :     }
     324                 :   else
     325                 :     {
     326               2 :       st = PDF_EBADDATA;
     327                 :     }  
     328                 : 
     329              14 :   return st;
     330                 : 
     331                 : }
     332                 : 
     333                 : 
     334                 : pdf_status_t
     335                 : pdf_hash_iterator_new (const pdf_hash_t table, pdf_hash_iterator_t *iterator)
     336               5 : {
     337                 :   pdf_status_t st;
     338                 : 
     339               5 :   st = PDF_OK;
     340                 : 
     341               5 :   if (iterator != NULL)
     342                 :     {
     343               8 :       *((gl_list_iterator_t*)iterator->gl_itr) =
     344                 :         gl_list_iterator ((gl_list_t)table.keys);
     345                 :     }
     346                 :   else
     347                 :     {
     348               1 :       st = PDF_EBADDATA;
     349                 :     }
     350                 : 
     351               5 :   return st;
     352                 : 
     353                 : }
     354                 : 
     355                 : 
     356                 : pdf_status_t
     357                 : pdf_hash_iterator_next (pdf_hash_iterator_t iterator, const char **key)
     358               2 : {
     359                 :   pdf_status_t st;
     360                 : 
     361               2 :   st = PDF_OK;
     362                 : 
     363               2 :   if (key != NULL)
     364                 :     {
     365               2 :       if (!gl_list_iterator_next((gl_list_iterator_t*)iterator.gl_itr,
     366                 :                                  (const void**)key, NULL))
     367                 :         {
     368               0 :           st = PDF_ERROR;
     369                 :         }    
     370                 :     }
     371                 :   else
     372                 :     {
     373               1 :       st = PDF_EBADDATA;
     374                 :     }
     375                 : 
     376               2 :   return st;
     377                 : }
     378                 : 
     379                 : 
     380                 : pdf_status_t
     381                 : pdf_hash_iterator_destroy (pdf_hash_iterator_t iterator)
     382               4 : {
     383                 : 
     384               4 :   if (iterator.gl_itr != NULL)
     385                 :     {
     386               4 :       gl_list_iterator_free ((gl_list_iterator_t*)iterator.gl_itr);
     387                 :     }
     388                 : 
     389               4 :   return PDF_OK;
     390                 : }
     391                 : 
     392                 : 
     393                 : 
     394                 : 
     395                 : 
     396                 : static size_t
     397                 : hash_pjw (const void *elt)
     398              57 : {
     399                 :   const pdf_hash_element_t *hashelem;
     400                 :   const char *s;
     401              57 :   size_t h = 0;
     402                 : 
     403              57 :   hashelem = (const pdf_hash_element_t*) elt;
     404                 : 
     405             285 :   for (s = hashelem->key; *s; s++)
     406             228 :     h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
     407                 : 
     408              57 :   return h;
     409                 : }
     410                 : 
     411                 : 
     412                 : void
     413                 : pdf_hash_element_dealloc_fn (const void * elt)
     414               0 : {
     415               0 :   pdf_dealloc(elt);
     416               0 : }
     417                 : 
     418                 : 
     419                 : void
     420                 : pdf_hash_key_dealloc_fn (const void * elt)
     421               0 : {
     422               0 :   pdf_dealloc(elt);
     423               0 : }
     424                 : 
     425                 : 
     426                 : static bool
     427                 : elem_key_equal (const void *elt1, const void *elt2)
     428              13 : {
     429                 :   const char *key1, *key2;
     430                 : 
     431              13 :   key1 = ((pdf_hash_element_t*)elt1)->key;
     432              13 :   key2 = ((pdf_hash_element_t*)elt2)->key;
     433                 :   
     434              13 :   return (!strcmp(key1,key2));
     435                 : }
     436                 : 
     437                 : 
     438                 : static bool
     439                 : key_equal (const void *key1, const void *key2)
     440               0 : {
     441               0 :   return (!strcmp((const char*)key1,(const char*)key2));
     442                 : }
     443                 : 
     444                 : 
     445                 : static int
     446                 : key_numeric_p (const char *str)
     447                 : {
     448             130 :   if (str != NULL && *str != '\0')
     449                 :     {
     450             191 :       while (*str != '\0')
     451                 :         {
     452             171 :           if (*str < '0' || *str > '9')
     453                 :             {
     454             110 :               return 0;
     455                 :             }  
     456              61 :           str++;
     457                 :         }
     458                 : 
     459              20 :       return 1;
     460                 :     }
     461                 : 
     462               0 :   return 0;
     463                 : }
     464                 : 
     465                 : 
     466                 : static int
     467                 : key_numeric_cmp (const char *key1, const char *key2)
     468                 : {
     469                 :   unsigned int num1, num2;
     470                 :   char *end_char;
     471                 : 
     472                 :   /* Note that no error checking is made here */
     473               6 :   num1 = (int) strtol (key1, &end_char, 10);
     474               6 :   num2 = (int) strtol (key2, &end_char, 10);
     475                 : 
     476               6 :   if (num1 > num2)
     477                 :     {
     478               5 :       return 1;
     479                 :     }
     480               1 :   else if (num1 < num2)
     481                 :     {
     482               1 :       return -1;
     483                 :     }
     484               0 :   return 0;
     485                 : }
     486                 : 
     487                 : 
     488                 : static int
     489                 : key_compare (const void *key1, const void *key2)
     490              65 : {
     491             130 :   if (key_numeric_p(key1))
     492                 :     {
     493              12 :       if (key_numeric_p(key2))
     494                 :         {
     495              12 :           return (key_numeric_cmp(key1, key2));
     496                 :         }
     497                 :       /* key2 is non-numeric so key1 > key2 */
     498               0 :       return 1;
     499                 :     }
     500                 :   /* key1 non-numeric */
     501             118 :   if (key_numeric_p(key2))
     502                 :     {
     503               8 :       return -1;
     504                 :     }
     505                 :   /* both are non-numeric */
     506              51 :   return (strcmp((const char*)key1,(const char*)key2));
     507                 : }
     508                 : 
     509                 : 
     510                 : /* End of pdf-hash.c */

Generated by: LTP GCOV extension version 1.6