(root)/
freetype-2.13.2/
src/
base/
fthash.c
       1  /****************************************************************************
       2   *
       3   * fthash.c
       4   *
       5   *   Hashing functions (body).
       6   *
       7   */
       8  
       9  /*
      10   * Copyright 2000 Computing Research Labs, New Mexico State University
      11   * Copyright 2001-2015
      12   *   Francesco Zappa Nardelli
      13   *
      14   * Permission is hereby granted, free of charge, to any person obtaining a
      15   * copy of this software and associated documentation files (the "Software"),
      16   * to deal in the Software without restriction, including without limitation
      17   * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18   * and/or sell copies of the Software, and to permit persons to whom the
      19   * Software is furnished to do so, subject to the following conditions:
      20   *
      21   * The above copyright notice and this permission notice shall be included in
      22   * all copies or substantial portions of the Software.
      23   *
      24   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      25   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      27   * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
      28   * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
      29   * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
      30   * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      31   */
      32  
      33    /**************************************************************************
      34     *
      35     * This file is based on code from bdf.c,v 1.22 2000/03/16 20:08:50
      36     *
      37     * taken from Mark Leisher's xmbdfed package
      38     *
      39     */
      40  
      41  
      42  #include <freetype/internal/fthash.h>
      43  #include <freetype/internal/ftmemory.h>
      44  
      45  
      46  #define INITIAL_HT_SIZE  241
      47  
      48  
      49    static FT_ULong
      50    hash_str_lookup( FT_Hashkey*  key )
      51    {
      52      const char*  kp  = key->str;
      53      FT_ULong     res = 0;
      54  
      55  
      56      /* Mocklisp hash function. */
      57      while ( *kp )
      58        res = ( res << 5 ) - res + (FT_ULong)*kp++;
      59  
      60      return res;
      61    }
      62  
      63  
      64    static FT_ULong
      65    hash_num_lookup( FT_Hashkey*  key )
      66    {
      67      FT_ULong  num = (FT_ULong)key->num;
      68      FT_ULong  res;
      69  
      70  
      71      /* Mocklisp hash function. */
      72      res = num & 0xFF;
      73      res = ( res << 5 ) - res + ( ( num >>  8 ) & 0xFF );
      74      res = ( res << 5 ) - res + ( ( num >> 16 ) & 0xFF );
      75      res = ( res << 5 ) - res + ( ( num >> 24 ) & 0xFF );
      76  
      77      return res;
      78    }
      79  
      80  
      81    static FT_Bool
      82    hash_str_compare( FT_Hashkey*  a,
      83                      FT_Hashkey*  b )
      84    {
      85      if ( a->str[0] == b->str[0]           &&
      86           ft_strcmp( a->str, b->str ) == 0 )
      87        return 1;
      88  
      89      return 0;
      90    }
      91  
      92  
      93    static FT_Bool
      94    hash_num_compare( FT_Hashkey*  a,
      95                      FT_Hashkey*  b )
      96    {
      97      if ( a->num == b->num )
      98        return 1;
      99  
     100      return 0;
     101    }
     102  
     103  
     104    static FT_Hashnode*
     105    hash_bucket( FT_Hashkey  key,
     106                 FT_Hash     hash )
     107    {
     108      FT_ULong      res = 0;
     109      FT_Hashnode*  bp  = hash->table;
     110      FT_Hashnode*  ndp;
     111  
     112  
     113      res = (hash->lookup)( &key );
     114  
     115      ndp = bp + ( res % hash->size );
     116      while ( *ndp )
     117      {
     118        if ( (hash->compare)( &(*ndp)->key, &key ) )
     119          break;
     120  
     121        ndp--;
     122        if ( ndp < bp )
     123          ndp = bp + ( hash->size - 1 );
     124      }
     125  
     126      return ndp;
     127    }
     128  
     129  
     130    static FT_Error
     131    hash_rehash( FT_Hash    hash,
     132                 FT_Memory  memory )
     133    {
     134      FT_Hashnode*  obp = hash->table;
     135      FT_Hashnode*  bp;
     136      FT_Hashnode*  nbp;
     137  
     138      FT_UInt   i, sz = hash->size;
     139      FT_Error  error = FT_Err_Ok;
     140  
     141  
     142      hash->size <<= 1;
     143      hash->limit  = hash->size / 3;
     144  
     145      if ( FT_NEW_ARRAY( hash->table, hash->size ) )
     146        goto Exit;
     147  
     148      for ( i = 0, bp = obp; i < sz; i++, bp++ )
     149      {
     150        if ( *bp )
     151        {
     152          nbp = hash_bucket( (*bp)->key, hash );
     153          *nbp = *bp;
     154        }
     155      }
     156  
     157      FT_FREE( obp );
     158  
     159    Exit:
     160      return error;
     161    }
     162  
     163  
     164    static FT_Error
     165    hash_init( FT_Hash    hash,
     166               FT_Bool    is_num,
     167               FT_Memory  memory )
     168    {
     169      FT_UInt   sz = INITIAL_HT_SIZE;
     170      FT_Error  error;
     171  
     172  
     173      hash->size  = sz;
     174      hash->limit = sz / 3;
     175      hash->used  = 0;
     176  
     177      if ( is_num )
     178      {
     179        hash->lookup  = hash_num_lookup;
     180        hash->compare = hash_num_compare;
     181      }
     182      else
     183      {
     184        hash->lookup  = hash_str_lookup;
     185        hash->compare = hash_str_compare;
     186      }
     187  
     188      FT_MEM_NEW_ARRAY( hash->table, sz );
     189  
     190      return error;
     191    }
     192  
     193  
     194    FT_Error
     195    ft_hash_str_init( FT_Hash    hash,
     196                      FT_Memory  memory )
     197    {
     198      return hash_init( hash, 0, memory );
     199    }
     200  
     201  
     202    FT_Error
     203    ft_hash_num_init( FT_Hash    hash,
     204                      FT_Memory  memory )
     205    {
     206      return hash_init( hash, 1, memory );
     207    }
     208  
     209  
     210    void
     211    ft_hash_str_free( FT_Hash    hash,
     212                      FT_Memory  memory )
     213    {
     214      if ( hash )
     215      {
     216        FT_UInt       sz = hash->size;
     217        FT_Hashnode*  bp = hash->table;
     218        FT_UInt       i;
     219  
     220  
     221        for ( i = 0; i < sz; i++, bp++ )
     222          FT_FREE( *bp );
     223  
     224        FT_FREE( hash->table );
     225      }
     226    }
     227  
     228  
     229    /* `ft_hash_num_free' is the same as `ft_hash_str_free' */
     230  
     231  
     232    static FT_Error
     233    hash_insert( FT_Hashkey  key,
     234                 size_t      data,
     235                 FT_Hash     hash,
     236                 FT_Memory   memory )
     237    {
     238      FT_Hashnode   nn;
     239      FT_Hashnode*  bp    = hash_bucket( key, hash );
     240      FT_Error      error = FT_Err_Ok;
     241  
     242  
     243      nn = *bp;
     244      if ( !nn )
     245      {
     246        if ( FT_QNEW( nn ) )
     247          goto Exit;
     248        *bp = nn;
     249  
     250        nn->key  = key;
     251        nn->data = data;
     252  
     253        if ( hash->used >= hash->limit )
     254        {
     255          error = hash_rehash( hash, memory );
     256          if ( error )
     257            goto Exit;
     258        }
     259  
     260        hash->used++;
     261      }
     262      else
     263        nn->data = data;
     264  
     265    Exit:
     266      return error;
     267    }
     268  
     269  
     270    FT_Error
     271    ft_hash_str_insert( const char*  key,
     272                        size_t       data,
     273                        FT_Hash      hash,
     274                        FT_Memory    memory )
     275    {
     276      FT_Hashkey  hk;
     277  
     278  
     279      hk.str = key;
     280  
     281      return hash_insert( hk, data, hash, memory );
     282    }
     283  
     284  
     285    FT_Error
     286    ft_hash_num_insert( FT_Int     num,
     287                        size_t     data,
     288                        FT_Hash    hash,
     289                        FT_Memory  memory )
     290    {
     291      FT_Hashkey  hk;
     292  
     293  
     294      hk.num = num;
     295  
     296      return hash_insert( hk, data, hash, memory );
     297    }
     298  
     299  
     300    static size_t*
     301    hash_lookup( FT_Hashkey  key,
     302                 FT_Hash     hash )
     303    {
     304      FT_Hashnode*  np = hash_bucket( key, hash );
     305  
     306  
     307      return (*np) ? &(*np)->data
     308                   : NULL;
     309    }
     310  
     311  
     312    size_t*
     313    ft_hash_str_lookup( const char*  key,
     314                        FT_Hash      hash )
     315    {
     316      FT_Hashkey  hk;
     317  
     318  
     319      hk.str = key;
     320  
     321      return hash_lookup( hk, hash );
     322    }
     323  
     324  
     325    size_t*
     326    ft_hash_num_lookup( FT_Int   num,
     327                        FT_Hash  hash )
     328    {
     329      FT_Hashkey  hk;
     330  
     331  
     332      hk.num = num;
     333  
     334      return hash_lookup( hk, hash );
     335    }
     336  
     337  
     338  /* END */