|
Blender
V2.59
|
00001 /* 00002 * $Id: STR_HashedString.h 35160 2011-02-25 11:51:19Z jesterking $ 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): none yet. 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00042 #ifndef __STR_HASHSTRING 00043 #define __STR_HASHSTRING 00044 00045 #include "STR_String.h" 00046 00047 00048 // Hash Mix utility function, by Bob Jenkins - Mix 3 32-bit values reversibly 00049 // 00050 // - If gHashMix() is run forward or backward, at least 32 bits in a,b,c have at 00051 // least 1/4 probability of changing. 00052 // 00053 // - If gHashMix() is run forward, every bit of c will change between 1/3 and 00054 // 2/3 of the time. 00055 // 00056 static inline void STR_gHashMix(dword& a, dword& b, dword& c) 00057 { 00058 a -= b; a -= c; a ^= (c>>13); 00059 b -= c; b -= a; b ^= (a<<8); 00060 c -= a; c -= b; c ^= (b>>13); 00061 a -= b; a -= c; a ^= (c>>12); 00062 b -= c; b -= a; b ^= (a<<16); 00063 c -= a; c -= b; c ^= (b>>5); 00064 a -= b; a -= c; a ^= (c>>3); 00065 b -= c; b -= a; b ^= (a<<10); 00066 c -= a; c -= b; c ^= (b>>15); 00067 } 00068 00069 // 00070 // Fast Hashable<int32> functionality 00071 // http://www.concentric.net/~Ttwang/tech/inthash.htm 00072 // 00073 static inline dword STR_gHash(dword inDWord) 00074 { 00075 dword key = inDWord; 00076 key += ~(key << 16); 00077 key ^= (key >> 5); 00078 key += (key << 3); 00079 key ^= (key >> 13); 00080 key += ~(key << 9); 00081 key ^= (key >> 17); 00082 return key; 00083 } 00084 00085 enum { GOLDEN_RATIO = 0x9e3779b9 }; // arbitrary value to initialize hash funtion, well not so arbitrary 00086 // as this value is taken from the pigs library (Orange Games/Lost Boys) 00087 00088 00089 00090 static dword STR_gHash(const void* in, int len, dword init_val) 00091 { 00092 unsigned int length = len; 00093 dword a = (dword)GOLDEN_RATIO; 00094 dword b = (dword)GOLDEN_RATIO; 00095 dword c = init_val; // the previous hash value 00096 byte *p_in = (byte *)in; 00097 00098 // Do the largest part of the key 00099 while (length >= 12) 00100 { 00101 a += (p_in[0] + ((dword)p_in[1]<<8) + ((dword)p_in[2] <<16) + ((dword)p_in[3] <<24)); 00102 b += (p_in[4] + ((dword)p_in[5]<<8) + ((dword)p_in[6] <<16) + ((dword)p_in[7] <<24)); 00103 c += (p_in[8] + ((dword)p_in[9]<<8) + ((dword)p_in[10]<<16) + ((dword)p_in[11]<<24)); 00104 STR_gHashMix(a, b, c); 00105 p_in += 12; length -= 12; 00106 } 00107 00108 // Handle the last 11 bytes 00109 c += len; 00110 switch(length) { 00111 case 11: c+=((dword)p_in[10]<<24); 00112 case 10: c+=((dword)p_in[9]<<16); 00113 case 9 : c+=((dword)p_in[8]<<8); // the first byte of c is reserved for the length 00114 case 8 : b+=((dword)p_in[7]<<24); 00115 case 7 : b+=((dword)p_in[6]<<16); 00116 case 6 : b+=((dword)p_in[5]<<8); 00117 case 5 : b+=p_in[4]; 00118 case 4 : a+=((dword)p_in[3]<<24); 00119 case 3 : a+=((dword)p_in[2]<<16); 00120 case 2 : a+=((dword)p_in[1]<<8); 00121 case 1 : a+=p_in[0]; 00122 } 00123 STR_gHashMix(a, b, c); 00124 00125 return c; 00126 } 00127 00128 00129 00130 00131 class STR_HashedString : public STR_String 00132 { 00133 public: 00134 STR_HashedString() : STR_String(),m_Hashed(false) {} 00135 STR_HashedString(const char* str) : STR_String(str),m_Hashed(false) {} 00136 STR_HashedString(const STR_String& str) : STR_String(str),m_Hashed(false) {} 00137 00138 inline dword hash(dword init=0) const 00139 { 00140 if (!m_Hashed) 00141 { 00142 const char* str = *this; 00143 int length = this->Length(); 00144 m_CachedHash = STR_gHash(str,length,init); 00145 m_Hashed=true; 00146 } 00147 return m_CachedHash; 00148 } 00149 00150 private: 00151 mutable bool m_Hashed; 00152 mutable dword m_CachedHash; 00153 }; 00154 00155 #endif //__STR_HASHSTRING 00156