Index: gperf/src/gperf/3.0.1/gperf-3.0.1-src/src/hash-table.cc |
=================================================================== |
--- gperf/src/gperf/3.0.1/gperf-3.0.1-src/src/hash-table.cc (revision 0) |
+++ gperf/src/gperf/3.0.1/gperf-3.0.1-src/src/hash-table.cc (revision 0) |
@@ -0,0 +1,167 @@ |
+/* Hash table for checking keyword links. Implemented using double hashing. |
+ Copyright (C) 1989-1998, 2000, 2002 Free Software Foundation, Inc. |
+ Written by Douglas C. Schmidt <schmidt@ics.uci.edu> |
+ and Bruno Haible <bruno@clisp.org>. |
+ |
+ This file is part of GNU GPERF. |
+ |
+ GNU GPERF is free software; you can redistribute it and/or modify |
+ it under the terms of the GNU General Public License as published by |
+ the Free Software Foundation; either version 2, or (at your option) |
+ any later version. |
+ |
+ GNU GPERF is distributed in the hope that it will be useful, |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ GNU General Public License for more details. |
+ |
+ You should have received a copy of the GNU General Public License |
+ along with this program; see the file COPYING. |
+ If not, write to the Free Software Foundation, Inc., |
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
+ |
+/* Specification. */ |
+#include "hash-table.h" |
+ |
+#include <stdio.h> |
+#include <string.h> /* declares memset(), strcmp() */ |
+#include <hash.h> |
+#include "options.h" |
+ |
+/* We use a hash table with double hashing. This is the simplest kind of |
+ hash table, given that we always only insert and never remove entries |
+ from the hash table. */ |
+ |
+/* To make double hashing efficient, there need to be enough spare entries. */ |
+static const int size_factor = 10; |
+ |
+/* We make the size of the hash table a power of 2. This allows for two |
+ optimizations: It eliminates the modulo instruction, and allows for an |
+ easy secondary hashing function. */ |
+ |
+/* Constructor. */ |
+Hash_Table::Hash_Table (unsigned int size, bool ignore_length) |
+ : _ignore_length (ignore_length), |
+ _collisions (0) |
+{ |
+ /* There need to be enough spare entries. */ |
+ size = size * size_factor; |
+ |
+ /* Find smallest power of 2 that is >= size. */ |
+ unsigned int shift = 0; |
+ if ((size >> 16) > 0) |
+ { |
+ size = size >> 16; |
+ shift += 16; |
+ } |
+ if ((size >> 8) > 0) |
+ { |
+ size = size >> 8; |
+ shift += 8; |
+ } |
+ if ((size >> 4) > 0) |
+ { |
+ size = size >> 4; |
+ shift += 4; |
+ } |
+ if ((size >> 2) > 0) |
+ { |
+ size = size >> 2; |
+ shift += 2; |
+ } |
+ if ((size >> 1) > 0) |
+ { |
+ size = size >> 1; |
+ shift += 1; |
+ } |
+ _log_size = shift; |
+ _size = 1 << shift; |
+ |
+ /* Allocate table. */ |
+ _table = new KeywordExt*[_size]; |
+ memset (_table, 0, _size * sizeof (*_table)); |
+} |
+ |
+/* Destructor. */ |
+Hash_Table::~Hash_Table () |
+{ |
+ delete[] _table; |
+} |
+ |
+/* Print the table's contents. */ |
+void |
+Hash_Table::dump () const |
+{ |
+ int field_width; |
+ |
+ field_width = 0; |
+ { |
+ for (int i = _size - 1; i >= 0; i--) |
+ if (_table[i]) |
+ if (field_width < _table[i]->_selchars_length) |
+ field_width = _table[i]->_selchars_length; |
+ } |
+ |
+ fprintf (stderr, |
+ "\ndumping the hash table\n" |
+ "total available table slots = %d, total bytes = %d, total collisions = %d\n" |
+ "location, %*s, keyword\n", |
+ _size, _size * static_cast<unsigned int>(sizeof (*_table)), |
+ _collisions, field_width, "keysig"); |
+ |
+ for (int i = _size - 1; i >= 0; i--) |
+ if (_table[i]) |
+ { |
+ fprintf (stderr, "%8d, ", i); |
+ if (field_width > _table[i]->_selchars_length) |
+ fprintf (stderr, "%*s", field_width - _table[i]->_selchars_length, ""); |
+ for (int j = 0; j < _table[i]->_selchars_length; j++) |
+ putc (_table[i]->_selchars[j], stderr); |
+ fprintf (stderr, ", %.*s\n", |
+ _table[i]->_allchars_length, _table[i]->_allchars); |
+ } |
+ |
+ fprintf (stderr, "\nend dumping hash table\n\n"); |
+} |
+ |
+/* Compares two items. */ |
+inline bool |
+Hash_Table::equal (KeywordExt *item1, KeywordExt *item2) const |
+{ |
+ return item1->_selchars_length == item2->_selchars_length |
+ && memcmp (item1->_selchars, item2->_selchars, |
+ item2->_selchars_length * sizeof (unsigned int)) |
+ == 0 |
+ && (_ignore_length |
+ || item1->_allchars_length == item2->_allchars_length); |
+} |
+ |
+/* Attempts to insert ITEM in the table. If there is already an equal |
+ entry in it, returns it. Otherwise inserts ITEM and returns NULL. */ |
+KeywordExt * |
+Hash_Table::insert (KeywordExt *item) |
+{ |
+ unsigned hash_val = |
+ hashpjw (reinterpret_cast<const unsigned char *>(item->_selchars), |
+ item->_selchars_length * sizeof (unsigned int)); |
+ unsigned int probe = hash_val & (_size - 1); |
+ unsigned int increment = |
+ (((hash_val >> _log_size) |
+ ^ (_ignore_length ? 0 : item->_allchars_length)) |
+ << 1) + 1; |
+ /* Note that because _size is a power of 2 and increment is odd, |
+ we have gcd(increment,_size) = 1, which guarantees that we'll find |
+ an empty entry during the loop. */ |
+ |
+ while (_table[probe] != NULL) |
+ { |
+ if (equal (_table[probe], item)) |
+ return _table[probe]; |
+ |
+ _collisions++; |
+ probe = (probe + increment) & (_size - 1); |
+ } |
+ |
+ _table[probe] = item; |
+ return NULL; |
+} |
Property changes on: gperf\src\gperf\3.0.1\gperf-3.0.1-src\src\hash-table.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |