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 #include <stdlib.h>
00024 #include <string.h>
00025 #include <ctype.h>
00026
00027 #include "hi_util_kmap.h"
00028 #include "hi_util_xmalloc.h"
00029
00030
00031
00032 #define MEMASSERT(p)
00033 #define LOWERCASE tolower
00034
00035
00036
00037
00038 static void * s_malloc( int n )
00039 {
00040 void * p;
00041
00042 p = xmalloc( n );
00043
00044 MEMASSERT(p);
00045
00046 return p;
00047 }
00048
00049
00050
00051
00052 static void s_free( void * p )
00053 {
00054 if( p ) xfree( p );
00055 }
00056
00057
00058
00059 KMAP * KMapNew( void (*userfree)(void*p) )
00060 {
00061 KMAP * km = (KMAP*) s_malloc( sizeof(KMAP) );
00062
00063 if( !km ) return 0;
00064
00065 memset(km, 0, sizeof(KMAP));
00066
00067 km->userfree = userfree;
00068
00069 return km;
00070 }
00071
00072
00073
00074 void KMapSetNoCase( KMAP * km, int flag )
00075 {
00076 km->nocase = flag;
00077 }
00078
00079
00080
00081
00082 static int KMapFreeNodeList(KMAP * km )
00083 {
00084 KEYNODE * k, *kold;
00085
00086 for( k=km->keylist; k; )
00087 {
00088 if( k->key )
00089 {
00090 s_free( k->key );
00091 }
00092 if( km->userfree && k->userdata )
00093 {
00094 km->userfree( k->userdata );
00095 }
00096 kold = k;
00097 k = k->next;
00098 s_free(kold);
00099 }
00100
00101 return 0;
00102 }
00103
00104
00105
00106 static void KMapFreeNode( KMAP * km, KMAPNODE * r)
00107 {
00108 if( r->sibling )
00109 {
00110 KMapFreeNode( km, r->sibling );
00111 }
00112
00113 if( r->child )
00114 {
00115 KMapFreeNode( km, r->child );
00116 }
00117
00118 s_free( r );
00119 }
00120
00121
00122
00123 void KMapDelete( KMAP * km )
00124 {
00125 KMAPNODE * r;
00126 int i;
00127
00128
00129 for(i=0;i<256;i++)
00130 {
00131 r = km->root[i];
00132 if( r )
00133 {
00134 KMapFreeNode(km,r);
00135 }
00136 }
00137
00138
00139 KMapFreeNodeList( km );
00140
00141 s_free(km);
00142 }
00143
00144
00145
00146
00147 static KEYNODE * KMapAddKeyNode(KMAP * km,void * key, int n, void * userdata )
00148 {
00149 KEYNODE * knode = (KEYNODE*) s_malloc( sizeof(KEYNODE) );
00150
00151 if( !knode || n < 0 )
00152 return 0;
00153
00154 memset(knode, 0, sizeof(KEYNODE) );
00155
00156 knode->key = (unsigned char*)s_malloc(n);
00157 if( !knode->key )
00158 return 0;
00159
00160 memcpy(knode->key,key,n);
00161 knode->nkey = n;
00162 knode->userdata = userdata;
00163
00164 if( km->keylist )
00165 {
00166 knode->next = km->keylist;
00167 km->keylist = knode;
00168 }
00169 else
00170 {
00171 km->keylist = knode;
00172 }
00173
00174 return knode;
00175 }
00176
00177
00178
00179 static KMAPNODE * KMapCreateNode(KMAP * km)
00180 {
00181 KMAPNODE * mn=(KMAPNODE*)s_malloc( sizeof(KMAPNODE) );
00182
00183 if(!mn)
00184 return NULL;
00185
00186 memset(mn,0,sizeof(KMAPNODE));
00187
00188 km->nchars++;
00189
00190 return mn;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 int KMapAdd( KMAP *km, void * key, int n, void * userdata )
00206 {
00207 int i,ksize;
00208 int type;
00209 unsigned char *P = (unsigned char *)key;
00210 KMAPNODE *root;
00211 unsigned char xkey[256];
00212
00213 if( n <= 0 )
00214 {
00215 n = strlen( (char*) key );
00216 if( n > sizeof(xkey) )
00217 return -99;
00218 }
00219
00220 if( km->nocase )
00221 {
00222 for(i=0;i<n;i++)
00223 xkey[i] = LOWERCASE( P[i] );
00224 P = xkey;
00225 }
00226
00227
00228 ksize = n;
00229
00230
00231
00232
00233 if( !km->root[ *P ] )
00234 {
00235 root = KMapCreateNode(km);
00236 if( !root )
00237 return -1;
00238 km->root[ *P ] = root;
00239 root->nodechar = *P;
00240
00241 }else{
00242
00243 root = km->root[ *P ];
00244 }
00245
00246
00247 while( n )
00248 {
00249 if( root->nodechar == *P )
00250 {
00251
00252 P++;
00253 n--;
00254 if( n && root->child )
00255 {
00256 root=root->child;
00257 }
00258 else
00259 {
00260 type = 0;
00261 break;
00262 }
00263 }
00264 else
00265 {
00266 if( root->sibling )
00267 {
00268 root=root->sibling;
00269 }
00270 else
00271 {
00272 type = 1;
00273 break;
00274 }
00275 }
00276 }
00277
00278
00279
00280
00281
00282 if( n )
00283 {
00284 if( type == 0 )
00285 {
00286
00287
00288
00289
00290 root->child= KMapCreateNode( km );
00291 if( !root->child )
00292 return -1;
00293 root=root->child;
00294 root->nodechar = *P;
00295 P++;
00296 n--;
00297 }
00298 else
00299 {
00300
00301
00302
00303
00304 root->sibling= KMapCreateNode( km );
00305 if( !root->sibling )
00306 return -1;
00307 root=root->sibling;
00308 root->nodechar = *P;
00309 P++;
00310 n--;
00311 }
00312 }
00313
00314
00315
00316
00317 while( n )
00318 {
00319
00320 root->child = KMapCreateNode(km);
00321 if( !root->child )
00322 return -1;
00323 root=root->child;
00324 root->nodechar = *P;
00325 P++;
00326 n--;
00327 }
00328
00329
00330
00331
00332
00333
00334 if( root->knode )
00335 return 1;
00336
00337 root->knode = KMapAddKeyNode( km, key, ksize, userdata );
00338 if( !root->knode )
00339 return -1;
00340
00341 return 0;
00342 }
00343
00344
00345
00346
00347
00348
00349 void * KMapFind( KMAP * ks, void * key, int n )
00350 {
00351 unsigned char * T = (unsigned char *)key;
00352 KMAPNODE * root;
00353 unsigned char xkey[256];
00354 int i;
00355
00356 if( n <= 0 )
00357 {
00358 n = strlen( (char*)key );
00359 if( n > sizeof(xkey) )
00360 return 0;
00361
00362 }
00363 if( ks->nocase )
00364 {
00365 for(i=0;i<n;i++)
00366 xkey[i] = LOWERCASE( T[i] );
00367
00368 T = xkey;
00369 }
00370
00371
00372
00373 root = ks->root[ *T ];
00374 if( !root ) return NULL;
00375
00376 while( n )
00377 {
00378 if( root->nodechar == *T )
00379 {
00380 T++;
00381 n--;
00382 if( n && root->child )
00383 {
00384 root = root->child;
00385 }
00386 else
00387 {
00388 break;
00389 }
00390 }
00391 else
00392 {
00393 if( root->sibling )
00394 {
00395 root = root->sibling;
00396 }
00397 else
00398 {
00399 break;
00400 }
00401 }
00402 }
00403
00404 if( !n )
00405 {
00406 if (root && root->knode)
00407 return root->knode->userdata;
00408 }
00409
00410 return NULL;
00411 }
00412
00413
00414
00415 KEYNODE * KMapFindFirstKey( KMAP * km )
00416 {
00417 km->keynext = km->keylist;
00418
00419 if(!km->keynext)
00420 {
00421 return NULL;
00422 }
00423
00424 return km->keynext;
00425 }
00426
00427
00428
00429 void * KMapFindFirst( KMAP * km )
00430 {
00431 km->keynext = km->keylist;
00432
00433 if(!km->keynext)
00434 {
00435 return NULL;
00436 }
00437
00438 return km->keynext->userdata;
00439 }
00440
00441
00442
00443 KEYNODE * KMapFindNextKey( KMAP * km )
00444 {
00445 if( !km->keynext )
00446 return 0;
00447
00448 km->keynext = km->keynext->next;
00449
00450 if( !km->keynext )
00451 return 0;
00452
00453 return km->keynext;
00454 }
00455
00456
00457
00458 void * KMapFindNext( KMAP * km )
00459 {
00460 if( !km->keynext )
00461 return 0;
00462
00463 km->keynext = km->keynext->next;
00464
00465 if( !km->keynext )
00466 return 0;
00467
00468 return km->keynext->userdata;
00469 }
00470
00471 #ifdef KMAP_MAIN
00472
00473
00474
00475 int main( int argc, char ** argv )
00476 {
00477 int i,n=10;
00478 KMAP * km;
00479 char * p;
00480 char str[80];
00481
00482 printf("usage: kmap nkeys (default=10)\n\n");
00483
00484 km = KMapNew( free );
00485
00486 KMapSetNoCase(km,1);
00487
00488 if( argc > 1 )
00489 {
00490 n = atoi(argv[1]);
00491 }
00492
00493 for(i=1;i<=n;i++)
00494 {
00495 sprintf(str,"KeyWord%d",i);
00496 KMapAdd( km, str, 0 , strupr(strdup(str)) );
00497 printf("Adding Key=%s\n",str);
00498 }
00499 printf("xmem: %u bytes, %d chars\n",xmalloc_bytes(),km->nchars);
00500
00501 printf("\nKey Find test...\n");
00502 for(i=1;i<=n;i++)
00503 {
00504 sprintf(str,"KeyWord%d",i);
00505 p = (char*) KMapFind( km, str, 0 );
00506 if(p)printf("key=%s, data=%*s\n",str,strlen(str),p);
00507 else printf("'%s' NOT found.\n",str);
00508 }
00509
00510 KMapSetNoCase(km,0);
00511 printf("\nKey Find test2...\n");
00512 for(i=1;i<=n;i++)
00513 {
00514 sprintf(str,"KeyWord%d",i);
00515 p = (char*) KMapFind( km, str, 0 );
00516 if(p)printf("key=%s, data=%*s\n",str,strlen(str),p);
00517 else printf("'%s' NOT found.\n",str);
00518 }
00519
00520 printf("\nKey FindFirst/Next test...\n");
00521 for(p = (char*) KMapFindFirst(km); p; p=(char*)KMapFindNext(km) )
00522 printf("data=%s\n",p);
00523
00524 printf("\nKey FindFirst/Next test done.\n");
00525
00526 KMapDelete( km );
00527
00528 printf("xmem: %u bytes\n",xmalloc_bytes());
00529
00530 printf("normal pgm finish.\n");
00531
00532 return 0;
00533 }
00534
00535 #endif
00536
00537