G:/ScriptBasic/source/extensions/hash/interface.c

Go to the documentation of this file.
00001 /* FILE:hash.c
00002 
00003 This file implements hash functionality for the ScriptBasic interpreter as
00004 an external module. The functions implemented in this file are:
00005 
00006 NewHash to create a new hash
00007 ReleaseHash to release a hash
00008 StartHash to reset hash iteration to the first key
00009 EndHash to set hash iteration to the last key
00010 NextHashKey to get the next hash key in iteration
00011 PreviousHashKey to get the previous key in iteration
00012 GetHashValue to get the value for the given key
00013 SetHashValue to set the value for the given key
00014 DeleteHashKey to delete a hash key entirely from the hash
00015 
00016 NTLIBS:
00017 UXLIBS:
00018 DWLIBS:
00019 MCLIBS:
00020 
00021 */
00022 #include <stdio.h>
00023 #define PRIME 211
00024 #include "../../basext.h"
00025 
00026 typedef struct _hashe {
00027   VARIABLE Key,Value;
00028   struct _hashe *small_son, *big_son;
00029   struct _hashe *next,*prev;
00030   } tHashE, *ptHashE;
00031 
00032 typedef struct _hash {
00033   ptHashE Table[PRIME];
00034   ptHashE FirstElement,
00035           LastElement,
00036           ThisElement;
00037   } tHash,*ptHash;
00038 typedef struct _myOBJECT {
00039   void *HandleArray;
00040   } myOBJECT, *pmyOBJECT;
00041 
00042 #define HASH_ERROR_INVALID_HASH_HANDLE 0x00080001
00043 #define HASH_ERROR_NO_CURRENT_ELEMENT  0x00080002
00044 #define HASH_ERROR_INVALID_VALUE       0x00080003
00045 #define HASH_ERROR_INTERNAL001         0x00080004
00046 #define HASH_ERROR_INTERNAL002         0x00080005
00047 
00048 /*
00049 
00050 varcmp compares two variables. The purpose of this function is to give
00051 some ordering when more than one keys have the same hash value and a binary
00052 tree has to be ordered. The function arbitrarily say that
00053 
00054 undef equals to undef only and is smaller than anything else
00055 double is smaller than a long (even 3.2 is smaller than 0).
00056 
00057 strings, longs and doubles are compared using their value and
00058 the natural comparision functions, operators.
00059 
00060 */
00061 static int varcmp(VARIABLE a, VARIABLE b){
00062   long minlen;
00063   int k;
00064 
00065   /* undef equals undef */
00066   if( a == NULL && b == NULL )return 0;
00067   /* undef is smaller than anything */
00068   if( a == NULL )return -1;
00069   if( b == NULL )return +1;
00070 
00071   /* compare strings */
00072   if( TYPE(a) == VTYPE_STRING && TYPE(b) == VTYPE_STRING ){
00073     minlen = STRLEN(a) < STRLEN(b) ? STRLEN(a) : STRLEN(b);
00074     k = memcmp(STRINGVALUE(a),STRINGVALUE(b),minlen);
00075     if( k == 0 && STRLEN(a) < STRLEN(b) )k = -1;
00076     if( k == 0 && STRLEN(a) > STRLEN(b) )k = +1;
00077     return k;
00078     }
00079   /* compare longs */
00080   if( TYPE(a) == VTYPE_LONG && TYPE(b) == VTYPE_LONG ){
00081     if( LONGVALUE(a) == LONGVALUE(b) )return 0;
00082     return LONGVALUE(a) < LONGVALUE(b) ? -1 : +1;
00083     }
00084   /* compare doubles */
00085   if( TYPE(a) == VTYPE_DOUBLE && TYPE(b) == VTYPE_DOUBLE ){
00086     if( DOUBLEVALUE(a) == DOUBLEVALUE(b) )return 0;
00087     return DOUBLEVALUE(a) < DOUBLEVALUE(b) ? -1 : +1;
00088     }
00089 
00090   /*
00091           GO ON AND COMPARE DIFFERENT TYPES HERE
00092    */
00093 
00094   /* string is smaller than any other type */
00095   if( TYPE(a) == VTYPE_STRING ) return -1;
00096   if( TYPE(b) == VTYPE_STRING ) return +1;
00097 
00098   /* long is smaller than double */
00099   if( TYPE(a) == VTYPE_LONG ) return -1;
00100   if( TYPE(b) == VTYPE_LONG ) return +1;
00101 
00102   /* we may end up here if both variables are arrays that they should not be. */
00103   return 0;
00104   }
00105 
00106 #define MASK  0xf0000000l
00107 static int hashpjw(char *s, long len){
00108   unsigned long h = 0, g;
00109   for ( ; len ; s++,len-- ) {
00110     h = (h << 4) + (*s);
00111     if (g = h&MASK) {
00112       h = h ^ (g >> 24);
00113       h = h ^ g;
00114     }
00115   }
00116   return h % PRIME;
00117 }
00118 
00119 static int varhashpjw(VARIABLE a){
00120 
00121   if( a == NULL )return 0;
00122   switch( TYPE(a) ){
00123     case VTYPE_STRING: return hashpjw(STRINGVALUE(a),STRLEN(a));
00124     case VTYPE_LONG:   return hashpjw((char *)&(LONGVALUE(a)),sizeof(long));
00125     case VTYPE_DOUBLE: return hashpjw((char *)&(DOUBLEVALUE(a)),sizeof(double));
00126     default: return 0;
00127     }
00128   }
00129 
00130 besVERSION_NEGOTIATE
00131 
00132   return (int)INTERFACE_VERSION;
00133 
00134 besEND
00135 
00136 besSUB_START
00137   pmyOBJECT p;
00138 
00139   besMODULEPOINTER = besALLOC(sizeof(myOBJECT));
00140   if( besMODULEPOINTER == NULL )return COMMAND_ERROR_MEMORY_LOW;
00141   p = (pmyOBJECT)besMODULEPOINTER;
00142   p->HandleArray = NULL;
00143 
00144 besEND
00145 
00146 besSUB_FINISH
00147   pmyOBJECT p;
00148 
00149   p = (pmyOBJECT)besMODULEPOINTER;
00150   if( p != NULL ){
00151     besHandleDestroyHandleArray(p->HandleArray);
00152     }
00153 besEND
00154 
00155 /*
00156   Create a new hash and return the handle of it.
00157 */
00158 besFUNCTION(newh)
00159   ptHash r;
00160   int i;
00161   pmyOBJECT p;
00162 
00163   p = (pmyOBJECT)besMODULEPOINTER;
00164   r = besALLOC(sizeof(tHash));
00165   if( r == NULL )return COMMAND_ERROR_MEMORY_LOW;
00166   r->FirstElement = NULL;
00167   r->LastElement = NULL;
00168   r->ThisElement = NULL;
00169   for( i = 0 ; i < PRIME ; i++ )r->Table[i] = NULL;
00170   besALLOC_RETURN_LONG;
00171   LONGVALUE(besRETURNVALUE) = besHandleGetHandle(p->HandleArray,r);
00172   return COMMAND_ERROR_SUCCESS;
00173 besEND
00174 
00175 #define GET_HASH_HANDLE \
00176   Argument = besARGUMENT(1);\
00177   besDEREFERENCE(Argument);\
00178   Argument = besCONVERT2LONG(Argument);\
00179   pH = besHandleGetPointer(p->HandleArray,LONGVALUE(Argument));
00180 
00181 besFUNCTION(sethv)
00182   VARIABLE Argument,vKey,vValue;
00183   int k;
00184   ptHash pH;
00185   ptHashE pE,*ppE;
00186   pmyOBJECT p;
00187 
00188   p = (pmyOBJECT)besMODULEPOINTER;
00189   besRETURNVALUE = NULL;
00190 
00191   if( besARGNR < 3 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00192 
00193   GET_HASH_HANDLE
00194 
00195   /* get the key */
00196   Argument = besARGUMENT(2);
00197   besDEREFERENCE(Argument);
00198   vKey = Argument;
00199 
00200   /* get the value, possibly a valid undef (aka NULL) */
00201   Argument = besARGUMENT(3);
00202   if( Argument ){
00203     besDEREFERENCE(Argument);
00204     /* make a local non-mortal copy of the argument */
00205     switch( Argument->vType ){
00206       case VTYPE_STRING:
00207         vValue = besNEWSTRING(STRLEN(Argument));
00208         if( vValue == NULL )return COMMAND_ERROR_MEMORY_LOW;
00209         memcpy(STRINGVALUE(vValue),STRINGVALUE(Argument),STRLEN(Argument));
00210         break;
00211       case VTYPE_LONG:
00212         vValue = besNEWLONG;
00213         if( vValue == NULL )return COMMAND_ERROR_MEMORY_LOW;
00214         LONGVALUE(vValue) = LONGVALUE(Argument);
00215         break;
00216       case VTYPE_DOUBLE:
00217         vValue = besNEWDOUBLE;
00218         if( vValue == NULL )return COMMAND_ERROR_MEMORY_LOW;
00219         DOUBLEVALUE(vValue) = DOUBLEVALUE(Argument);
00220         break;
00221       default: return HASH_ERROR_INVALID_VALUE;
00222       }
00223     }else vValue = NULL; /*this is a "copy" of undef*/
00224 
00225   /* try to find the key in the hash table */
00226   ppE = pH->Table+varhashpjw(vKey);
00227   while( *ppE ){
00228     k = varcmp(vKey,(*ppE)->Key);
00229     if( k == 0 )break;/* we have found the key */
00230     ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00231     }
00232 
00233   if( *ppE ){
00234     /* if the key exists, release the old value and insert the new */
00235     if( (*ppE)->Value )besRELEASE( (*ppE)->Value );
00236     (*ppE)->Value = vValue;
00237     return COMMAND_ERROR_SUCCESS;
00238     }
00239 
00240   /* 
00241          here we have to insert a new element
00242    */
00243 
00244   /* make a local non-mortal copy of the key value */
00245   Argument = vKey;
00246   if( Argument ){
00247     besDEREFERENCE(Argument);
00248     /* make a local non-mortal copy of the argument */
00249     switch( Argument->vType ){
00250       case VTYPE_STRING:
00251         vKey = besNEWSTRING(STRLEN(Argument));
00252         if( vKey == NULL )return COMMAND_ERROR_MEMORY_LOW;
00253         memcpy(STRINGVALUE(vKey),STRINGVALUE(Argument),STRLEN(Argument));
00254         break;
00255       case VTYPE_LONG:
00256         vKey = besNEWLONG;
00257         if( vKey == NULL )return COMMAND_ERROR_MEMORY_LOW;
00258         LONGVALUE(vKey) = LONGVALUE(Argument);
00259         break;
00260       case VTYPE_DOUBLE:
00261         vKey = besNEWDOUBLE;
00262         if( vKey == NULL )return COMMAND_ERROR_MEMORY_LOW;
00263         DOUBLEVALUE(vKey) = DOUBLEVALUE(Argument);
00264         break;
00265       default: return HASH_ERROR_INVALID_VALUE;
00266       }
00267     }else vKey = NULL; /*this is a "copy" of undef*/
00268 
00269   *ppE = pE = besALLOC(sizeof(tHashE));
00270   if( pE == NULL )return COMMAND_ERROR_MEMORY_LOW;
00271   pE->Key = vKey;
00272   pE->Value = vValue;
00273   pE->small_son = NULL;
00274   pE->big_son = NULL;
00275   pE->next = NULL;
00276   if( pH->LastElement ){
00277     pH->LastElement->next = pE;
00278     }else
00279     pH->LastElement = pE;
00280 
00281   if( pH->FirstElement == NULL ){
00282     pH->FirstElement = pE;
00283     pH->ThisElement = pE;
00284     pE->prev = NULL;
00285     }else
00286     pE->prev = pH->LastElement;
00287 
00288   pH->LastElement = pE;
00289 
00290 besEND
00291 
00292 besFUNCTION(gethv)
00293   VARIABLE Argument,vKey;
00294   int k;
00295   ptHash pH;
00296   ptHashE *ppE;
00297   pmyOBJECT p;
00298 
00299   p = (pmyOBJECT)besMODULEPOINTER;
00300   besRETURNVALUE = NULL;
00301 
00302   if( besARGNR < 2 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00303 
00304   GET_HASH_HANDLE
00305 
00306   /* get the key */
00307   Argument = besARGUMENT(2);
00308   besDEREFERENCE(Argument);
00309   vKey = Argument;
00310 
00311   /* try to find the key in the hash table */
00312   ppE = pH->Table+varhashpjw(vKey);
00313   while( *ppE ){
00314     k = varcmp(vKey,(*ppE)->Key);
00315     if( k == 0 )break;/* we have found the key */
00316     ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00317     }
00318 
00319   pH->ThisElement = *ppE;
00320 
00321   /* if the key does not exists, we return undef */
00322   if( *ppE == NULL )return COMMAND_ERROR_SUCCESS;
00323 
00324   /* return a reference value to the value */
00325   besRETURNVALUE  = besNEWMORTALREF;
00326   if( besRETURNVALUE  == NULL )return COMMAND_ERROR_MEMORY_LOW;
00327   besRETURNVALUE->Value.aValue = &((*ppE)->Value);
00328 
00329 besEND
00330 
00331 besFUNCTION(ivhv)
00332   VARIABLE Argument,vKey;
00333   int k;
00334   ptHash pH;
00335   ptHashE *ppE;
00336   pmyOBJECT p;
00337 
00338   p = (pmyOBJECT)besMODULEPOINTER;
00339 
00340   besRETURNVALUE = NULL;
00341 
00342   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00343 
00344   GET_HASH_HANDLE
00345 
00346   if( besARGNR == 1 ){/*no key, see the iteration pointer */
00347   besALLOC_RETURN_LONG;
00348   /* if the key does not exists, we return false */
00349     if( pH->ThisElement == NULL ){
00350       LONGVALUE(besRETURNVALUE) = 0L;
00351       }else{
00352       LONGVALUE(besRETURNVALUE) = 1L;
00353       }
00354     return COMMAND_ERROR_SUCCESS;
00355     }
00356 
00357   /* get the key */
00358   Argument = besARGUMENT(2);
00359   besDEREFERENCE(Argument);
00360   vKey = Argument;
00361 
00362   /* try to find the key in the hash table */
00363   ppE = pH->Table+varhashpjw(vKey);
00364   while( *ppE ){
00365     k = varcmp(vKey,(*ppE)->Key);
00366     if( k == 0 )break;/* we have found the key */
00367     ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00368     }
00369 
00370   pH->ThisElement = *ppE;
00371 
00372   besALLOC_RETURN_LONG;
00373   /* if the key does not exists, we return false */
00374   if( *ppE == NULL ){
00375     LONGVALUE(besRETURNVALUE) = 0L;
00376     }else{
00377     LONGVALUE(besRETURNVALUE) = 1L;
00378     }
00379   return COMMAND_ERROR_SUCCESS;
00380 
00381 besEND
00382 
00383 besFUNCTION(delhk)
00384   VARIABLE Argument,vKey;
00385   unsigned long minlen;
00386   int k;
00387   ptHash pH;
00388   ptHashE pE,*ppE;
00389   pmyOBJECT p;
00390 
00391   p = (pmyOBJECT)besMODULEPOINTER;
00392 
00393   besRETURNVALUE = NULL;
00394 
00395   if( besARGNR < 2 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00396 
00397   GET_HASH_HANDLE
00398 
00399   /* get the key */
00400   Argument = besARGUMENT(2);
00401   besDEREFERENCE(Argument);
00402   if( Argument != NULL )
00403     vKey = besCONVERT2STRING(Argument);
00404   else
00405     vKey = NULL;
00406 
00407   /* try to find the key in the hash table */
00408   ppE = pH->Table+varhashpjw(vKey);
00409   while( *ppE ){
00410     minlen = vKey ? STRLEN(vKey) : 0;
00411     if( minlen > STRLEN( (*ppE)->Key ) )minlen = STRLEN( (*ppE)->Key );
00412     k = varcmp(vKey,(*ppE)->Key);
00413     if( k == 0 )break;/* we have found the key */
00414     ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00415     }
00416 
00417   /* if the key does not exist the it is no problem trying to delete it */
00418   if( *ppE == NULL )return COMMAND_ERROR_SUCCESS;
00419 
00420   /* if the key exists, release the old value and insert the new */
00421   if( (*ppE)->Value )besRELEASE( (*ppE)->Value );
00422   if( (*ppE)->Key   )besRELEASE( (*ppE)->Key   );
00423 
00424   /* unlink from the linked list */
00425   if( (*ppE)->next )(*ppE)->next->prev = (*ppE)->prev;
00426   if( (*ppE)->prev )(*ppE)->prev->next = (*ppE)->next;
00427 
00428   if( (*ppE)->prev == NULL )
00429     /* this was the first element */
00430     pH->FirstElement = (*ppE)->next;
00431 
00432   if( (*ppE)->next == NULL )
00433     /* this was the last element */
00434     pH->LastElement = (*ppE)->prev;
00435 
00436   pH->ThisElement = NULL; /* to be safe, we may have just destroyed the actual element,
00437                              and I hate comparing pointers*/
00438 
00439   pE = *ppE;
00440 
00441   (*ppE) = pE->big_son; /* we hook big son on the place of the curently deleted record */
00442 
00443   if( pE->small_son ){/* if there is small son */
00444     vKey = pE->small_son->Key;
00445     while( *ppE ){
00446       minlen = vKey ? STRLEN(vKey) : 0;
00447       if( minlen > STRLEN( (*ppE)->Key ) )minlen = STRLEN( (*ppE)->Key );
00448       k = varcmp(vKey,(*ppE)->Key);
00449       if( k == 0 )break;/* we have found the key */
00450       ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00451       }
00452    if( *ppE ){
00453      /* If *ppE is not NULL it means that we have found the key. But the key belongs to
00454         a node of the hash that was already inserted and currently off hooked. We just
00455         could not find the one that holds this key therefore getting here means that the
00456         key is duplicated. On the other hand keys can not be duplicated, so this means
00457         an internal error. I hope that this is dead code and I wish to have a C compiler
00458         that optimizes to the level recognising it.
00459      */
00460      return HASH_ERROR_INTERNAL001;
00461      }
00462    *ppE = pE->small_son; /* hook small son pon its new place */
00463    }
00464   besFREE(pE);/* finally release the node */
00465 besEND
00466 
00467 besFUNCTION(starth)
00468   VARIABLE Argument;
00469   ptHash pH;
00470   pmyOBJECT p;
00471 
00472   p = (pmyOBJECT)besMODULEPOINTER;
00473 
00474   besRETURNVALUE = NULL;
00475 
00476   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00477 
00478   GET_HASH_HANDLE
00479 
00480   pH->ThisElement = pH->FirstElement;
00481 besEND
00482 
00483 besFUNCTION(endh)
00484   VARIABLE Argument;
00485   ptHash pH;
00486   pmyOBJECT p;
00487 
00488   p = (pmyOBJECT)besMODULEPOINTER;
00489 
00490   besRETURNVALUE = NULL;
00491 
00492   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00493 
00494   GET_HASH_HANDLE
00495 
00496   pH->ThisElement = pH->LastElement;
00497 besEND
00498 
00499 besFUNCTION(nexthk)
00500   VARIABLE Argument;
00501   ptHash pH;
00502   pmyOBJECT p;
00503 
00504   p = (pmyOBJECT)besMODULEPOINTER;
00505 
00506   besRETURNVALUE = NULL;
00507 
00508   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00509 
00510   GET_HASH_HANDLE
00511 
00512   if( pH->ThisElement == NULL )return HASH_ERROR_NO_CURRENT_ELEMENT;
00513   pH->ThisElement = pH->ThisElement->next;
00514   if( pH->ThisElement == NULL || pH->ThisElement->Key == NULL )return COMMAND_ERROR_SUCCESS;
00515   switch( pH->ThisElement->Key->vType ){
00516     case VTYPE_STRING:
00517       besALLOC_RETURN_STRING(STRLEN(pH->ThisElement->Key));
00518       memcpy(STRINGVALUE(besRETURNVALUE),STRINGVALUE(pH->ThisElement->Key),STRLEN(pH->ThisElement->Key));
00519       return COMMAND_ERROR_SUCCESS;
00520     case VTYPE_LONG:
00521       besALLOC_RETURN_LONG;
00522       LONGVALUE(besRETURNVALUE) = LONGVALUE(pH->ThisElement->Key);
00523       return COMMAND_ERROR_SUCCESS;
00524     case VTYPE_DOUBLE:
00525       besALLOC_RETURN_DOUBLE;
00526       DOUBLEVALUE(besRETURNVALUE) = DOUBLEVALUE(pH->ThisElement->Key);
00527       return COMMAND_ERROR_SUCCESS;
00528     default: return HASH_ERROR_INTERNAL002;
00529     }
00530 besEND
00531 
00532 besFUNCTION(pervhk)
00533   VARIABLE Argument;
00534   ptHash pH;
00535   pmyOBJECT p;
00536 
00537   p = (pmyOBJECT)besMODULEPOINTER;
00538 
00539   besRETURNVALUE = NULL;
00540 
00541   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00542 
00543   GET_HASH_HANDLE
00544 
00545   if( pH->ThisElement == NULL )return HASH_ERROR_NO_CURRENT_ELEMENT;
00546   pH->ThisElement = pH->ThisElement->prev;
00547   if( pH->ThisElement == NULL || pH->ThisElement->Key == NULL )return COMMAND_ERROR_SUCCESS;
00548   switch( pH->ThisElement->Key->vType ){
00549     case VTYPE_STRING:
00550       besALLOC_RETURN_STRING(STRLEN(pH->ThisElement->Key));
00551       memcpy(STRINGVALUE(besRETURNVALUE),STRINGVALUE(pH->ThisElement->Key),STRLEN(pH->ThisElement->Key));
00552       return COMMAND_ERROR_SUCCESS;
00553     case VTYPE_LONG:
00554       besALLOC_RETURN_LONG;
00555       LONGVALUE(besRETURNVALUE) = LONGVALUE(pH->ThisElement->Key);
00556       return COMMAND_ERROR_SUCCESS;
00557     case VTYPE_DOUBLE:
00558       besALLOC_RETURN_DOUBLE;
00559       DOUBLEVALUE(besRETURNVALUE) = DOUBLEVALUE(pH->ThisElement->Key);
00560       return COMMAND_ERROR_SUCCESS;
00561     default: return HASH_ERROR_INTERNAL002;
00562     }
00563 besEND
00564 
00565 besFUNCTION(thishk)
00566   VARIABLE Argument;
00567   ptHash pH;
00568   pmyOBJECT p;
00569 
00570   p = (pmyOBJECT)besMODULEPOINTER;
00571 
00572   besRETURNVALUE = NULL;
00573 
00574   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00575 
00576   GET_HASH_HANDLE
00577 
00578   if( pH->ThisElement == NULL )return HASH_ERROR_NO_CURRENT_ELEMENT;
00579   if( pH->ThisElement->Key == NULL )return COMMAND_ERROR_SUCCESS;
00580   switch( pH->ThisElement->Key->vType ){
00581     case VTYPE_STRING:
00582       besALLOC_RETURN_STRING(STRLEN(pH->ThisElement->Key));
00583       memcpy(STRINGVALUE(besRETURNVALUE),STRINGVALUE(pH->ThisElement->Key),STRLEN(pH->ThisElement->Key));
00584       return COMMAND_ERROR_SUCCESS;
00585     case VTYPE_LONG:
00586       besALLOC_RETURN_LONG;
00587       LONGVALUE(besRETURNVALUE) = LONGVALUE(pH->ThisElement->Key);
00588       return COMMAND_ERROR_SUCCESS;
00589     case VTYPE_DOUBLE:
00590       besALLOC_RETURN_DOUBLE;
00591       DOUBLEVALUE(besRETURNVALUE) = DOUBLEVALUE(pH->ThisElement->Key);
00592       return COMMAND_ERROR_SUCCESS;
00593     default: return HASH_ERROR_INTERNAL002;
00594     }
00595 besEND
00596 
00597 besFUNCTION(thishv)
00598   VARIABLE Argument;
00599   ptHash pH;
00600   pmyOBJECT p;
00601 
00602   p = (pmyOBJECT)besMODULEPOINTER;
00603 
00604   besRETURNVALUE = NULL;
00605 
00606   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00607 
00608   GET_HASH_HANDLE
00609 
00610   if( pH->ThisElement == NULL )return HASH_ERROR_NO_CURRENT_ELEMENT;
00611   /* return a reference value to the value */
00612   besRETURNVALUE  = besNEWMORTALREF;
00613   if( besRETURNVALUE  == NULL )return COMMAND_ERROR_MEMORY_LOW;
00614   besRETURNVALUE->Value.aValue = &(pH->ThisElement->Value);
00615 besEND
00616 
00617 besFUNCTION(relh)
00618   VARIABLE Argument;
00619   ptHash pH;
00620   LEFTVALUE Lval;
00621   unsigned long __refcount_;
00622   pmyOBJECT p;
00623 
00624   p = (pmyOBJECT)besMODULEPOINTER;
00625 
00626   besRETURNVALUE = NULL;
00627 
00628   if( besARGNR < 1 )return EX_ERROR_TOO_FEW_ARGUMENTS;
00629 
00630   GET_HASH_HANDLE
00631 
00632   while( pH->FirstElement ){
00633     pH->ThisElement = pH->FirstElement;
00634     pH->FirstElement = pH->FirstElement->next;
00635     besRELEASE(pH->ThisElement->Key);
00636     besRELEASE(pH->ThisElement->Value);
00637     besFREE(pH->ThisElement);
00638     }
00639   besFREE(pH);
00640 
00641   /* if the argument is a variable, and I hope it is, then undef it
00642      so that it will not later be mistakenly used */
00643   Argument = besARGUMENT(1);
00644   besLEFTVALUE(Argument,Lval);
00645   if( Lval ){
00646     besRELEASE(*Lval);
00647     *Lval = NULL;
00648     }
00649 besEND

Generated on Sun Mar 12 23:56:28 2006 for ScriptBasic by  doxygen 1.4.6-NO