ghash.cpp

Go to the documentation of this file.
00001 // ghash.cpp -- Version 0.1
00002 
00003 #include <string.h>
00004 #include "ghash.h"
00005 ////////////////////////////////////////////////////////////
00006 // Static members
00007 // ---------------------------------------------------------
00008 // void!
00009 
00010 gKey::gKey (eKeyKind aKeyKind)
00011     : keyKind( aKeyKind ),
00012       pvalUInt( nil ),
00013       pvalDouble( nil )
00014 {
00015 }
00016 
00017 gKey::gKey (int v)
00018     : gInt( v ),
00019       pvalUInt( nil ),
00020       pvalDouble( nil )
00021 {
00022  keyKind = gKey::e_Int;
00023 }
00024 
00025 gKey::gKey (gInt& v)
00026     : gInt( v.GetInt() ),
00027       pvalUInt( nil ),
00028       pvalDouble( nil )
00029 {
00030  keyKind = gKey::e_Int;
00031 }
00032 
00033 gKey::gKey (gString& s)
00034     : gInt( -1 ),
00035       pvalUInt( nil ),
00036       pvalDouble( nil ),
00037       pvalStr( s )
00038 {
00039  keyKind = gKey::e_String;
00040 }
00041 
00042 gKey::gKey (char* s)
00043     : gInt( -1 ),
00044       pvalUInt( nil ),
00045       pvalDouble( nil )
00046 {
00047  pvalStr.Set( s );
00048  keyKind = gKey::e_String;
00049 }
00050 
00051 gKey::~gKey ()
00052 {
00053  delete pvalUInt;
00054  delete pvalDouble;
00055 }
00056 
00057 bool gKey::IsOk ()
00058 {
00059  return true;
00060 }
00061 
00062 t_uint64 gKey::GetUInt64 ()
00063 {
00064  ASSERTION(pvalUInt!=nil,"pvalUInt!=nil");
00065  return *pvalUInt;
00066 }
00067 
00068 double gKey::GetReal ()
00069 {
00070  ASSERTION(pvalDouble!=nil,"pvalDouble!=nil");
00071  return *pvalDouble;
00072 }
00073 
00074 gString& gKey::GetString ()
00075 {
00076  ASSERTION(pvalUInt==nil,"pvalUInt==nil");
00077  ASSERTION(pvalDouble==nil,"pvalDouble==nil");
00078  ASSERTION(GetInt()<=0,"GetInt()<=0");
00079  ASSERTION(keyKind==gKey::e_String,"keyKind=e_String");
00080  return pvalStr;
00081 }
00082 
00083 unsigned gKey::HashPos (unsigned hashSize)
00084 {
00085 #ifdef DEBUG_HASH
00086  return 1; //For debugging, it is easier...
00087 #else
00088  unsigned uTemp;
00089  double dTemp;
00090 
00091  switch ( keyKind ) {
00092  case gKey::e_Int:
00093      return (unsigned)GetInt()%hashSize;
00094  case gKey::e_UInt64:
00095      return (unsigned)(*pvalUInt)%hashSize;
00096  case gKey::e_Real:
00097      dTemp = *pvalDouble;
00098      uTemp = dTemp > (double)MAX_LONG_L ? (unsigned)(dTemp/214748364.0) : (unsigned)(dTemp*101.0);
00099      return uTemp%hashSize;
00100  case gKey::e_String:
00101      return HashStrPos( hashSize, pvalStr );
00102  default:
00103      ASSERTION_FALSE("HashPos(1)");
00104  }
00105  return 0;
00106 #endif //DEBUG_HASH
00107 }
00108 
00109 bool gKey::MatchKey (gKey& hKey)
00110 {
00111  ; // Note: hKey.keyKind must match our keyKind
00112  if ( keyKind!=hKey.GetKeyKind() ) return false;
00113  if ( hKey.IsOk()==false ) return false; //Academic...
00114  switch ( keyKind ) {
00115  case gKey::e_Int:
00116      return GetInt()==hKey.GetInt();
00117  case gKey::e_UInt64:
00118      return GetUInt64()==hKey.GetUInt64();
00119  case gKey::e_Real:
00120      return GetReal()==hKey.GetReal();
00121  case gKey::e_String:
00122      return GetString().Match( hKey.GetString() );
00123  default:
00124      ASSERTION_FALSE("MatchKey(1)");
00125  }
00126  return false;
00127 }
00128 
00129 bool gKey::MatchStorage (gStorage* aObj)
00130 {
00131  gHashElemGeneric* pHashElem;
00132  ASSERTION(aObj!=nil,"aObj!=nil");
00133  ASSERTION(aObj->Kind()==e_Control,"aObj->Kind()==e_Control");
00134  pHashElem = (gHashElemGeneric*)aObj;
00135  return MatchKey( pHashElem->hKey );
00136 }
00137 
00138 void gKey::Reset ()
00139 {
00140  gInt::Reset();
00141  if ( pvalUInt!=nil ) *pvalUInt = 0;
00142  if ( pvalDouble!=nil ) *pvalDouble = 0.0;
00143  pvalStr.SetEmpty();
00144 }
00145 
00146 void gKey::Set (int v)
00147 {
00148  thisNewKind( gKey::e_Int );
00149  SetInt( v );
00150 }
00151 
00152 void gKey::Set (t_uint64 v)
00153 {
00154  thisNewKind( gKey::e_UInt64 );
00155  ASSERTION(pvalUInt!=nil,"pvalUInt!=nil");
00156  *pvalUInt = v;
00157 }
00158 
00159 void gKey::Set (double v)
00160 {
00161  thisNewKind( gKey::e_Real );
00162  ASSERTION(pvalDouble!=nil,"pvalDouble!=nil");
00163  *pvalDouble = v;
00164 }
00165 
00166 void gKey::Set (gString& s)
00167 {
00168  thisNewKind( gKey::e_String );
00169  pvalStr = s;
00170 }
00171 
00172 void gKey::Copy (gKey& copy)
00173 {
00174  eKeyKind newKind = copy.GetKeyKind();
00175  switch ( newKind ) {
00176  case gKey::e_Int:
00177      Set( copy.GetInt() );
00178      break;
00179  case gKey::e_UInt64:
00180      Set( copy.GetUInt64() );
00181      break;
00182  case gKey::e_Real:
00183      Set( copy.GetReal() );
00184      break;
00185  case gKey::e_String:
00186      Set( copy.GetString() );
00187      break;
00188  default:
00189      ASSERTION_FALSE("gKey::Copy(1)");
00190  }
00191  ASSERTION(keyKind==newKind,"gKey::Copy(2)");
00192 }
00193 
00194 unsigned gKey::HashStrPos (unsigned hashSize, gString& s)
00195 {
00196  unsigned i, n, uTemp=0, uMark;
00197  t_uchar uChr;
00198  // This method, in particular with hashSize=7591 (instead of default 971),
00199  // leaves only one element in each row for HTML tags.
00200  if ( hashSize==7591 && s.Match("FORM") ) return 1519;
00201  for (i=1, n=s.Length(); i<=n; i++) {
00202      uChr = s[i];
00203      uMark = uChr>='a' && uChr<='z' ? (unsigned)uChr-32 : (unsigned)uChr;
00204      uMark -= 65;
00205      if ( i==1 ) uMark *= hashSize / 26;
00206      uTemp += uMark+i*2+(uChr>='Y');
00207  }
00208  //printf("%u\tHASH_STR_POS(%s)\n",uTemp%hashSize,s.Str());
00209  return uTemp%hashSize;
00210 }
00211 
00212 gStorage* gKey::NewObject ()
00213 {
00214  ASSERTION_FALSE("gKey::NewObject");
00215  return nil;
00216 }
00217 
00218 t_uchar* gKey::ToString (t_uchar* uBuf)
00219 {
00220  char* sBuf;
00221  if ( uBuf==nil ) return nil;
00222  sBuf = (char*)uBuf;
00223  switch ( keyKind ) {
00224  case gKey::e_Int:
00225      sprintf(sBuf,"%d",GetInt());
00226      break;
00227  case gKey::e_UInt64:
00228      sprintf(sBuf,"%lx",(long)GetUInt64());
00229      break;
00230  case gKey::e_Real:
00231      sprintf(sBuf,"%f",(float)GetReal());
00232      break;
00233  case gKey::e_String:
00234      sprintf(sBuf,"%s",GetString().Str());
00235      break;
00236  default:
00237      ASSERTION_FALSE("gKey::ToString");
00238  }
00239  return (t_uchar*)sBuf;
00240 }
00241 
00242 void gKey::Show (bool doShowAll)
00243 {
00244  t_uchar uBuf[50];
00245  printf("%s",ToString(uBuf));
00246 }
00247 
00248 void gKey::thisNewKind (eKeyKind newKind)
00249 {
00250  Reset();
00251  delete pvalUInt;
00252  pvalUInt = nil;
00253  delete pvalDouble;
00254  pvalDouble = nil;
00255  switch ( keyKind = newKind ) {
00256  case gKey::e_Int:
00257      break;
00258  case gKey::e_UInt64:
00259      pvalUInt = new t_uint64;
00260      break;
00261  case gKey::e_Real:
00262      pvalDouble = new double;
00263      break;
00264  case gKey::e_String:
00265      break;
00266  default:
00267      ASSERTION_FALSE("thisNewKind");
00268  };
00269 }
00270 ////////////////////////////////////////////////////////////
00271 gHashElemGeneric::gHashElemGeneric (gStorage* aObj)
00272     : myObj( aObj )
00273 {
00274 }
00275 
00276 gHashElemGeneric::~gHashElemGeneric ()
00277 {
00278  // myObj is not allocated ever!
00279 }
00280 
00281 gHashElemTriple::gHashElemTriple (gKey& aKey, gString& s, gStorage* aObj)
00282     : gHashElemGeneric( aObj ),
00283       sDesc( s ),
00284       iVal( 0 )
00285 {
00286  hKey.Copy( aKey );
00287 }
00288 
00289 gHashElemTriple::gHashElemTriple (gKey& aKey, int aVal, gStorage* aObj)
00290     : gHashElemGeneric( aObj ),
00291       iVal( aVal )
00292 {
00293  hKey.Copy( aKey );
00294 }
00295 
00296 gHashElemTriple::~gHashElemTriple ()
00297 {
00298 }
00299 
00300 void gHashElemTriple::Show (bool doShowAll)
00301 {
00302  hKey.Show( doShowAll );
00303  if ( doShowAll ) {
00304      printf("{%s",sDesc.Str());
00305      /*if ( myObj!=nil ) {
00306          printf("[");
00307          myObj->Show( true );
00308          printf("]\n");
00309      }
00310      NOTE: myObj is not copied!
00311      */
00312      printf("}");
00313  }
00314 }
00315 ////////////////////////////////////////////////////////////
00316 // gHashGeneric - Generic hash handling
00317 // ---------------------------------------------------------
00318 gHashGeneric::gHashGeneric (eStorage aKind, unsigned hashSize)
00319     : gStorage( aKind, e_StgDefault ),
00320       size( 0 ),
00321       pLst( nil ),
00322       usageCounter( 0 )
00323 {
00324  thisPreAllocate( hashSize );
00325 }
00326 
00327 gHashGeneric::~gHashGeneric ()
00328 {
00329  thisDelete();
00330 }
00331 
00332 bool gHashGeneric::IsValidIndex (unsigned idx)
00333 {
00334  return idx<size;
00335 }
00336 
00337 gList* gHashGeneric::GetHash (unsigned idx)
00338 {
00339  ASSERTION(pLst!=nil,"pLst!=nil");
00340  ASSERTION(IsValidIndex(idx),"GetHash(1)");
00341  return &pLst[idx];
00342 }
00343 
00344 unsigned gHashGeneric::Delete ()
00345 {
00346  thisDelete();
00347  thisPreAllocate( size );
00348  return size;
00349 }
00350 
00351 gStorage* gHashGeneric::NewObject ()
00352 {
00353  ASSERTION_FALSE("gHashGeneric::NewObject: Not used");
00354  return nil;
00355 }
00356 
00357 t_uchar* gHashGeneric::ToString (t_uchar* uBuf)
00358 {
00359  ;
00360  // Output notation:
00361  //     Empty hash               ===>    ()
00362  //     Hash of strings          ===>    (me and you)
00363  //     Hash of strings and nums ===>    (I am '31 years old)
00364  //     Hash of sentences        ===>    ("I use a suit." "You use a dress.")
00365  //     Hash with some resvd chrs.==>    (123-a.com sold '100 domains)
00366  ;
00367  return nil;
00368 }
00369 
00370 bool gHashGeneric::SaveGuts (FILE* f)
00371 {
00372  return CanSave( f );
00373 }
00374 
00375 bool gHashGeneric::RestoreGuts (FILE* f)
00376 {
00377  return CanRestore( f );
00378 }
00379 
00380 void gHashGeneric::thisPreAllocate (unsigned toSize)
00381 {
00382  ASSERTION(toSize>=LST_HASH_SIZE_MIN,"toSize>=101");
00383  ASSERTION(pLst==nil,"pLst==nil");
00384  pLst = new gList[ size = toSize ];
00385  ASSERTION(pLst!=nil,"pLst!=nil");
00386 }
00387 
00388 unsigned gHashGeneric::thisDelete ()
00389 {
00390  ASSERTION(pLst!=nil,"pLst!=nil");
00391  delete[] pLst;
00392  pLst = nil;
00393  return size;
00394 }
00395 ////////////////////////////////////////////////////////////
00396 gHash::gHash (unsigned hashSize)
00397     : gHashGeneric( e_List, hashSize ),
00398       doFindBeforeInsert( false )
00399 {
00400 }
00401 
00402 gHash::~gHash ()
00403 {
00404 }
00405 
00406 bool gHash::FindKey (gKey& hKey)
00407 {
00408  int x;
00409  int hashPos = thisFindKey( hKey, x );
00410  return hashPos>=0;
00411 }
00412 
00413 unsigned gHash::Add (int v)
00414 {
00415  gInt aVal( v );
00416  return Add( aVal );
00417 }
00418 
00419 unsigned gHash::Add (gInt& v)
00420 {
00421  gString sEmpty;
00422  return Add( v, sEmpty );
00423 }
00424 
00425 unsigned gHash::Add (gInt& v, gString& s)
00426 {
00427  gKey hKey( v );
00428  return Add( hKey, s );
00429 }
00430 
00431 unsigned gHash::Add (gKey& hKey, gString& s)
00432 {
00433  if ( doFindBeforeInsert ) {
00434      if ( FindKey( hKey ) ) return 0;
00435  }
00436  gHashElemTriple* pElem = new gHashElemTriple( hKey, s, nil/*No object needed*/ );
00437  ASSERTION(pElem!=nil,"pElem!=nil");
00438  thisAddElem( hKey.HashPos(size), pElem );
00439  return 0;
00440 }
00441 
00442 t_uchar* gHash::ToString (t_uchar* uBuf)
00443 {
00444  return gHashGeneric::ToString( uBuf );
00445 }
00446 
00447 bool gHash::SaveGuts (FILE* f)
00448 {
00449  return gHashGeneric::SaveGuts( f );
00450 }
00451 
00452 bool gHash::RestoreGuts (FILE* f)
00453 {
00454  return gHashGeneric::RestoreGuts( f );
00455 }
00456 
00457 void gHash::Show (bool doShowAll)
00458 {
00459  unsigned idx, k, n;
00460  unsigned count=0;
00461  gList* pRow;
00462  for (idx=0; idx<size; idx++) {
00463      pRow = GetHash( idx );
00464      n = pRow->N();
00465      if ( n==0 ) {
00466          ;//if ( doShowAll ) printf("(%u)",idx);
00467      }
00468      else {
00469          printf("%s%u:",count==0?"\0":" ",idx);
00470          count++;
00471          for (k=1; k<=n; k++) {
00472              gStorage* aObj = pRow->GetObjectPtr(k);
00473              ASSERTION(aObj!=nil,"aObj!=nil");
00474              aObj->Show( doShowAll );
00475          }
00476      }
00477  }
00478  if ( doShowAll ) printf("\n");
00479 }
00480 
00481 int gHash::thisAddElem (unsigned idx, gHashElemGeneric* pElem)
00482 {
00483  gList* pRow = GetHash( idx );
00484  bool mustBeOk = pRow->AppendObject( pElem );
00485  ASSERTION(mustBeOk,"thisAddElem(1)");
00486  thisInsertElement();
00487  return 0;
00488 }
00489 
00490 int gHash::thisFindKey (gKey& hKey, int& x)
00491 {
00492  unsigned idx = hKey.HashPos( size );
00493  gList* pRow = GetHash( idx );
00494  int n = (int)pRow->N();
00495  for (x=1; x<=n; x++) {
00496      if ( thisKeyMatch( hKey, pRow->GetObjectPtr(x) )==1 )
00497          return (int)idx;
00498  }
00499  // ...here, no matches
00500  x = 0;
00501  return -1;
00502 }
00503 
00504 int gHash::thisKeyMatch (gKey& hKey, gStorage* hashElem)
00505 {
00506  // Returns 1 if the 'hKey' matches the object 'hashElem'
00507  return (int)hKey.MatchStorage( hashElem );
00508 }
00509 
00510 #ifdef DEBUG_HASH
00511 bool gHash::AddTriplePos_dbg (unsigned idx, gKey& hKey, char* str)
00512 {
00513  gString s( str );
00514  gHashElemTriple* pElem = new gHashElemTriple( hKey, s, nil );
00515  thisAddElem( idx, pElem );
00516  return pElem!=nil;
00517 }
00518 #endif //DEBUG_HASH
00519 ////////////////////////////////////////////////////////////
00520 gHashTriple::gHashTriple (unsigned hashSize)
00521     : gHash( hashSize )
00522 {
00523 }
00524 
00525 gHashTriple::~gHashTriple ()
00526 {
00527 }
00528 
00529 bool gHashTriple::FindKey (gKey& hKey)
00530 {
00531  // Actually the same as in gHash: no need to redefine,
00532  // but here stated for easier expansion of double keys...
00533  return gHash::FindKey( hKey );
00534 }
00535 
00536 gHashElemTriple* gHashTriple::GetTriple (unsigned idx, int x)
00537 {
00538  gHashElemTriple* aObj;
00539  ASSERTION(x>=1,"x>=1");
00540  aObj = (gHashElemTriple*)GetHash( idx )->GetObjectPtr( (unsigned)x );
00541  // No need for assertion here, already in gList::GetObjectPtr!
00542  return aObj;
00543 }
00544 
00545 gHashElemTriple* gHashTriple::Find (gKey& hKey, unsigned& idx, int& x)
00546 {
00547  gHashElemTriple* pElem;
00548  idx = hKey.HashPos( size );
00549  gList* pRow = GetHash( idx );
00550  int n = (int)pRow->N();
00551  for (x=1; x<=n; x++) {
00552      pElem = (gHashElemTriple*)pRow->GetObjectPtr(x);
00553      if ( thisKeyMatch( hKey, pElem )==1 )
00554          return pElem;
00555  }
00556  x = 0;
00557  return nil;
00558 }
00559 
00560 bool gHashTriple::AddTriple (gKey& hKey, char* str, gStorage* aObj)
00561 {
00562  gString s( str );
00563  return AddTriple( hKey, s, aObj );
00564 }
00565 
00566 bool gHashTriple::AddTriple (gKey& hKey, gString& s, gStorage* aObj)
00567 {
00568  if ( doFindBeforeInsert ) {
00569      if ( FindKey( hKey ) ) return false;
00570  }
00571  gHashElemTriple* pElem = new gHashElemTriple( hKey, s, aObj );
00572  ASSERTION(pElem!=nil,"pElem!=nil");
00573  thisAddElem( hKey.HashPos(size), pElem );
00574  return true;
00575 }
00576 
00577 bool gHashTriple::AddTriple (gKey& hKey, int iVal, gStorage* aObj)
00578 {
00579  if ( doFindBeforeInsert ) {
00580      if ( FindKey( hKey ) ) return false;
00581  }
00582  gHashElemTriple* pElem = new gHashElemTriple( hKey, iVal, aObj );
00583  ASSERTION(pElem!=nil,"pElem!=nil");
00584  thisAddElem( hKey.HashPos(size), pElem );
00585  return true;
00586 }
00587 ////////////////////////////////////////////////////////////
00588 

Generated on Sat Aug 18 02:40:54 2007 for xpfweb_v2x lib by  doxygen 1.4.2