00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 static int varcmp(VARIABLE a, VARIABLE b){
00062 long minlen;
00063 int k;
00064
00065
00066 if( a == NULL && b == NULL )return 0;
00067
00068 if( a == NULL )return -1;
00069 if( b == NULL )return +1;
00070
00071
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
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
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
00092
00093
00094
00095 if( TYPE(a) == VTYPE_STRING ) return -1;
00096 if( TYPE(b) == VTYPE_STRING ) return +1;
00097
00098
00099 if( TYPE(a) == VTYPE_LONG ) return -1;
00100 if( TYPE(b) == VTYPE_LONG ) return +1;
00101
00102
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
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
00196 Argument = besARGUMENT(2);
00197 besDEREFERENCE(Argument);
00198 vKey = Argument;
00199
00200
00201 Argument = besARGUMENT(3);
00202 if( Argument ){
00203 besDEREFERENCE(Argument);
00204
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;
00224
00225
00226 ppE = pH->Table+varhashpjw(vKey);
00227 while( *ppE ){
00228 k = varcmp(vKey,(*ppE)->Key);
00229 if( k == 0 )break;
00230 ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00231 }
00232
00233 if( *ppE ){
00234
00235 if( (*ppE)->Value )besRELEASE( (*ppE)->Value );
00236 (*ppE)->Value = vValue;
00237 return COMMAND_ERROR_SUCCESS;
00238 }
00239
00240
00241
00242
00243
00244
00245 Argument = vKey;
00246 if( Argument ){
00247 besDEREFERENCE(Argument);
00248
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;
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
00307 Argument = besARGUMENT(2);
00308 besDEREFERENCE(Argument);
00309 vKey = Argument;
00310
00311
00312 ppE = pH->Table+varhashpjw(vKey);
00313 while( *ppE ){
00314 k = varcmp(vKey,(*ppE)->Key);
00315 if( k == 0 )break;
00316 ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00317 }
00318
00319 pH->ThisElement = *ppE;
00320
00321
00322 if( *ppE == NULL )return COMMAND_ERROR_SUCCESS;
00323
00324
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 ){
00347 besALLOC_RETURN_LONG;
00348
00349 if( pH->ThisElement == NULL ){
00350 LONGVALUE(besRETURNVALUE) = 0L;
00351 }else{
00352 LONGVALUE(besRETURNVALUE) = 1L;
00353 }
00354 return COMMAND_ERROR_SUCCESS;
00355 }
00356
00357
00358 Argument = besARGUMENT(2);
00359 besDEREFERENCE(Argument);
00360 vKey = Argument;
00361
00362
00363 ppE = pH->Table+varhashpjw(vKey);
00364 while( *ppE ){
00365 k = varcmp(vKey,(*ppE)->Key);
00366 if( k == 0 )break;
00367 ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00368 }
00369
00370 pH->ThisElement = *ppE;
00371
00372 besALLOC_RETURN_LONG;
00373
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
00400 Argument = besARGUMENT(2);
00401 besDEREFERENCE(Argument);
00402 if( Argument != NULL )
00403 vKey = besCONVERT2STRING(Argument);
00404 else
00405 vKey = NULL;
00406
00407
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;
00414 ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00415 }
00416
00417
00418 if( *ppE == NULL )return COMMAND_ERROR_SUCCESS;
00419
00420
00421 if( (*ppE)->Value )besRELEASE( (*ppE)->Value );
00422 if( (*ppE)->Key )besRELEASE( (*ppE)->Key );
00423
00424
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
00430 pH->FirstElement = (*ppE)->next;
00431
00432 if( (*ppE)->next == NULL )
00433
00434 pH->LastElement = (*ppE)->prev;
00435
00436 pH->ThisElement = NULL;
00437
00438
00439 pE = *ppE;
00440
00441 (*ppE) = pE->big_son;
00442
00443 if( pE->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;
00450 ppE = k < 0 ? &( (*ppE)->small_son ) : &( (*ppE)->big_son );
00451 }
00452 if( *ppE ){
00453
00454
00455
00456
00457
00458
00459
00460 return HASH_ERROR_INTERNAL001;
00461 }
00462 *ppE = pE->small_son;
00463 }
00464 besFREE(pE);
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
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
00642
00643 Argument = besARGUMENT(1);
00644 besLEFTVALUE(Argument,Lval);
00645 if( Lval ){
00646 besRELEASE(*Lval);
00647 *Lval = NULL;
00648 }
00649 besEND