Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

utils.c

Go to the documentation of this file.
00001 
00009 /* {{{ Initial headers */
00010 /*
00011  * $LastChangedDate: 2004-04-01 18:34:17 +0200 (Thu, 01 Apr 2004) $
00012  * $LastChangedRevision: 50 $
00013  * $LastChangedBy: ckruse $
00014  *
00015  */
00016 /* }}} */
00017 
00018 /* {{{ Includes */
00019 #include "config.h"
00020 #include "defines.h"
00021 
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <time.h>
00026 #include <ctype.h>
00027 #include <errno.h>
00028 
00029 #include <sys/time.h>
00030 
00031 #include "charconvert.h"
00032 #include "utils.h"
00033 /* }}} */
00034 
00035 /* {{{ memdup
00036  * Returns:  A pointer to the duplicated memory area
00037  * Parameters:
00038  *   - void *inptr  The pointer to the original memory area
00039  *   - size_t size  The size of the memory area
00040  *
00041  * This function duplicates a memory area
00042  *
00043  */
00044 void *memdup(void *inptr,size_t size) {
00045   void *outptr = fo_alloc(NULL,1,size,FO_ALLOC_MALLOC);
00046   memcpy(outptr,inptr,size);
00047 
00048   return outptr;
00049 }
00050 /* }}} */
00051 
00052 /* {{{ fo_alloc
00053  * Returns:     NULL on false type attribute, the new pointer in any else case
00054  * Parameters:
00055  *   - void *ptr     The old pointer for realloc()
00056  *   - size_t nmemb  The number of objects to allocate
00057  *   - size_t size   The size of one object
00058  *   - int type      The type of the allocation (FO_ALLOC_MALLOC, FO_ALLOC_CALLOC or FO_ALLOC_REALLOC)
00059  *
00060  * Safely allocates new memory
00061  */
00062 void *fo_alloc(void *ptr,size_t nmemb,size_t size,int type) {
00063   void *l_ptr = NULL;
00064 
00065   switch(type) {
00066   case FO_ALLOC_MALLOC:
00067     l_ptr = malloc(nmemb * size);
00068     break;
00069   case FO_ALLOC_CALLOC:
00070     l_ptr = calloc(nmemb,size);
00071     break;
00072   case FO_ALLOC_REALLOC:
00073     l_ptr = realloc(ptr,size * nmemb);
00074     break;
00075   }
00076 
00077   if(!l_ptr) {
00078     perror("error allocating memory");
00079     exit(EXIT_FAILURE);
00080   }
00081 
00082   return l_ptr;
00083 }
00084 /* }}} */
00085 
00086 /* {{{ split
00087  * Returns: long       the length of the list
00088  * Parameters:
00089  *   - const u_char *big     the string to split
00090  *   - const u_char *small   the string where to split
00091  *   - u_char ***list        the list
00092  *
00093  * This function splits a string into pieces
00094  *
00095  */
00096 size_t split(const u_char *big,const u_char *small,u_char ***ulist) {
00097   u_char **list  = fo_alloc(NULL,PRERESERVE,sizeof(*list),FO_ALLOC_MALLOC);
00098   u_char  *pos   = (u_char *)big,*pre = (u_char *)big;
00099   size_t len   = 0;
00100   size_t reser = PRERESERVE;
00101   size_t slen  = strlen(small);
00102 
00103   while((pos = strstr(pos,small)) != NULL) {
00104     *pos = '\0';
00105 
00106     list[len++] = strdup(pre);
00107 
00108     if(len >= reser) {
00109       reser += PRERESERVE;
00110       list = fo_alloc(list,reser,sizeof(*list),FO_ALLOC_REALLOC);
00111     }
00112 
00113     pre    = pos+slen;
00114     *pos++ = *small;
00115   }
00116 
00117   if(len >= reser) {
00118     list = fo_alloc(list,++reser,sizeof(*list),FO_ALLOC_REALLOC);
00119   }
00120   list[len++] = strdup(pre);
00121 
00122   list   = fo_alloc(list,len,sizeof(*list),FO_ALLOC_REALLOC);
00123   *ulist = list;
00124 
00125   return len;
00126 }
00127 /* }}} */
00128 
00129 /* {{{ mem_init */
00130 void mem_init(t_mem_pool *pool) {
00131   pool->len      = 0;
00132   pool->reserved = 0;
00133   pool->content  = NULL;
00134 }
00135 /* }}} */
00136 
00137 /* {{{ str_init
00138  * Returns: void   nothing
00139  * Parameters:
00140  *   - t_string *str        the string to append on
00141  *
00142  * this function initializes a string structure
00143  *
00144  */
00145 void str_init(t_string *str) {
00146   str->len      = 0;
00147   str->reserved = 0;
00148   str->content  = NULL;
00149 }
00150 /* }}} */
00151 
00152 /* {{{ mem_cleanup */
00153 void mem_cleanup(t_mem_pool *pool) {
00154   pool->len      = 0;
00155   pool->reserved = 0;
00156 
00157   if(pool->content) free(pool->content);
00158 
00159   pool->content  = NULL;
00160 }
00161 /* }}} */
00162 
00163 /* {{{ str_cleanup
00164  * Returns: void   nothing
00165  * Parameters:
00166  *   - t_string *str        the string to append on
00167  *
00168  * this function frees mem
00169  *
00170  */
00171 void str_cleanup(t_string *str) {
00172   str->len      = 0;
00173   str->reserved = 0;
00174 
00175   if(str->content) free(str->content);
00176 
00177   str->content  = NULL;
00178 }
00179 /* }}} */
00180 
00181 /* {{{ str_char_append
00182  * Returns: size_t   the number of chars appended
00183  * Parameters:
00184  *   - t_string *str        the string to append on
00185  *   - const u_char content  the character to append
00186  *
00187  * this function appends a const u_char to a t_string
00188  *
00189  */
00190 size_t str_char_append(t_string *str,const u_char content) {
00191   if(str->len + 1 >= str->reserved) {
00192     str->content   = fo_alloc(str->content,(size_t)(str->reserved + BUFSIZ),1,FO_ALLOC_REALLOC);
00193     str->reserved += BUFSIZ;
00194   }
00195 
00196   str->content[str->len] = content;
00197   str->len              += 1;
00198   str->content[str->len] = '\0';
00199 
00200   return 1;
00201 }
00202 /* }}} */
00203 
00204 /* {{{ str_chars_append
00205  * Returns: size_t   the number of chars appended
00206  * Parameters:
00207  *   - t_string *str        the string to append on
00208  *   - const u_char *content the string to append
00209  *   - int length           the length of the string to append
00210  *
00211  * this function appends a const u_char * string to a t_string
00212  *
00213  */
00214 size_t str_chars_append(t_string *str,const u_char *content,size_t length) {
00215   size_t len = BUFSIZ;
00216 
00217   if(str->len + length >= str->reserved) {
00218     if(length >= len) {
00219       len += length;
00220     }
00221 
00222     str->content   = fo_alloc(str->content,(size_t)(str->reserved + len),1,FO_ALLOC_REALLOC);
00223     str->reserved += len;
00224   }
00225 
00226   memcpy(&str->content[str->len],content,length);
00227   str->len += length;
00228   str->content[str->len] = '\0';
00229 
00230   return length;
00231 }
00232 /* }}} */
00233 
00234 /* {{{ str_equal_string
00235  * Returns: TRUE if both are equal, FALSE otherwise
00236  * Parameters:
00237  *   - str1 string 1
00238  *   - str2 string 2
00239  *
00240  * This function tests if two strings (t_string) are equal
00241  */
00242 int str_equal_string(const t_string *str1,const t_string *str2) {
00243   register u_char *ptr1 = str1->content,*ptr2 = str2->content;
00244   register size_t i;
00245 
00246   if(str1->len != str2->len) {
00247     return 1;
00248   }
00249 
00250   for(i = 0; i < str1->len; ++i,++ptr1,++ptr2) {
00251     if(*ptr1 != *ptr2) {
00252       return 1;
00253     }
00254   }
00255 
00256   return 0;
00257 }
00258 /* }}} */
00259 
00260 /* {{{ str_equal_chars
00261  * Returns: TRUE if both are equal, FALSE otherwise
00262  * Parameters:
00263  *   - str1 string 1
00264  *   - str2 string 2
00265  *   - len length of the c_string to be compared
00266  *
00267  * This function tests if two strings (t_string) are equal
00268  */
00269 int str_equal_chars(const t_string *str1,const u_char *str2, size_t len) {
00270   register size_t i = 0;
00271   register u_char *ptr1 = str1->content,*ptr2 = (u_char *)str2;
00272 
00273   if(str1->len != len) {
00274     return 1;
00275   }
00276 
00277   for(i = 0; i < len; ++i,++ptr1,++ptr2) {
00278     if(*ptr1 != *ptr2) {
00279       return 1;
00280     }
00281   }
00282 
00283   return 0;
00284 }
00285 /* }}} */
00286 
00287 /* {{{ mem_append */
00288 void *mem_append(t_mem_pool *pool,const void *src,size_t length) {
00289   size_t len = BUFSIZ;
00290 
00291   if(pool->len + length >= pool->reserved) {
00292     if(length >= len) {
00293       len += length;
00294     }
00295 
00296     pool->content   = fo_alloc(pool->content,(size_t)(pool->reserved + len),1,FO_ALLOC_REALLOC);
00297     pool->reserved += len;
00298   }
00299 
00300   memcpy(pool->content + pool->len,src,length);
00301   pool->len += length;
00302 
00303   return pool->content + pool->len - length;
00304 }
00305 /* }}} */
00306 
00307 /* {{{ str_str_append
00308  * Returns: void   nothing
00309  * Parameters:
00310  *   - t_string *str        the string to append on
00311  *   - t_string *content    the string to append
00312  *
00313  * this function is a wrapper, it calls str_chars_append
00314  *
00315  */
00316 size_t str_str_append(t_string *str,t_string *content) {
00317   return str_chars_append(str,content->content,content->len);
00318 }
00319 /* }}} */
00320 
00321 /* {{{ mem_set */
00322 size_t mem_set(t_mem_pool *pool,const void *src,size_t length) {
00323   size_t len = MAXLINE;
00324 
00325   if(pool->len + length >= pool->reserved) {
00326     if(length >= len) {
00327       len += length;
00328     }
00329 
00330     pool->content   = fo_alloc(pool->content,pool->reserved + len,1,FO_ALLOC_REALLOC);
00331     pool->reserved += len;
00332   }
00333 
00334   memcpy(pool->content,src,length);
00335   pool->len = length;
00336 
00337   return length;
00338 }
00339 /* }}} */
00340 
00341 /* {{{ str_char_set
00342  * Returns: void   nothing
00343  * Parameters:
00344  *   - t_string *str        the string to append on
00345  *   - const u_char *content the string to append
00346  *   - int length           the length of the string to append
00347  *
00348  * this function copies a const u_char * to a t_string.
00349  *
00350  */
00351 size_t str_char_set(t_string *str,const u_char *content,size_t length) {
00352   size_t len = BUFSIZ;
00353 
00354   if(str->len + length >= str->reserved) {
00355     if(length >= len) {
00356       len += length;
00357     }
00358 
00359     str->content   = fo_alloc(str->content,len,1,FO_ALLOC_REALLOC);
00360     str->reserved += BUFSIZ;
00361   }
00362 
00363   memcpy(str->content,content,length);
00364   str->len = length;
00365   str->content[length] = '\0';
00366 
00367   return length;
00368 }
00369 /* }}} */
00370 
00371 /* {{{ str_str_set
00372  * Returns: void   nothing
00373  * Parameters:
00374  *   - t_string *str        the string to append on
00375  *   - t_string *content    the string to append
00376  *
00377  * this function is a wrapper. it calls str_char_set
00378  *
00379  */
00380 size_t str_str_set(t_string *str,t_string *set) {
00381   return str_char_set(str,set->content,set->len);
00382 }
00383 /* }}} */
00384 
00385 /* {{{ transform_date
00386  * Returns: time_t          the timestamp or (time_t)0
00387  * Parameters:
00388  *   - const u_char *datestr the date string
00389  *
00390  * This function tries to create a timestamp
00391  *
00392  */
00393 time_t transform_date(const u_char *datestr) {
00394   struct tm t;
00395   u_char *ptr,*before;                     /* two pointers to work with */
00396   u_char *str = fo_alloc(NULL,strlen(datestr)+1,1,FO_ALLOC_MALLOC); /* we need a copy of the string (we cannot change a const u_char *) */
00397 
00398   (void)strcpy(str,datestr);
00399   ptr = before = str;
00400 
00401   memset(&t,0,sizeof(t));        /* initialize the struct tm (set everything to 0) */
00402 
00403   for(;*ptr && *ptr != '.';ptr++);       /* search the first . (for the day) */
00404   if(*ptr == '.') {                      /* if this is not a dot, we have no valid date */
00405     *ptr = '\0';                         /* setting this byte to 0, we can use atoi() whithout creating a substring */
00406     t.tm_mday = atoi(before);            /* fill the mont day (1-31) */
00407     *ptr = '.';
00408   }
00409   else {
00410     free(str);
00411     return (time_t)-1;                    /* no valid date */
00412   }
00413 
00414   for(before= ++ptr;*ptr && *ptr != '.';ptr++);        /* search the next dot (for the month) */
00415   if(*ptr == '.') {
00416     *ptr = '\0';
00417     t.tm_mon = atoi(before)-1;                         /* tm_mon contains the mont - 1 (0-11) */
00418     *ptr = '.';
00419   }
00420   else {
00421     free(str);
00422     return (time_t)-1;                                  /* no valid date */
00423   }
00424 
00425   for(before= ++ptr;*ptr && !isspace(*ptr);ptr++);     /* search the '\0' or a whitespace; if a whitespace
00426                                                         * follows, there are also hours and mins and perhaps seconds */
00427   if(isspace(*ptr) || *ptr == '\0') {                  /* Is this a a valid entry? */
00428     t.tm_year = atoi(before) - 1900;                   /* tm_year contains the year - 1900 */
00429   }
00430   else {
00431     free(str);
00432     return (time_t)-1;                                  /* not a valid entry */
00433   }
00434 
00435   if(*ptr == ' ') {                                    /* follows an hour and a minute? */
00436     for(;*ptr && *ptr == ' ';ptr++);                   /* skip trailing whitespaces */
00437 
00438     if(*ptr) {                                         /* have we got a string like "1.1.2001 "? */
00439       for(before= ++ptr;*ptr && *ptr != ':';ptr++);    /* search the next colon (Hours are seperated from minutes by
00440                     * colons
00441               */
00442       if(*ptr == ':') {
00443   *ptr = '\0';
00444   t.tm_hour = atoi(before);                      /* get the hour */
00445   *ptr = ':';
00446       }
00447       else {
00448   free(str);
00449   return (time_t)-1;
00450       }
00451 
00452       for(before= ++ptr;*ptr && *ptr != ':';ptr++);    /* search for the end of the string or another colon */
00453       if(*ptr == ':' || *ptr == '\0') {
00454   if(*ptr == ':') {
00455     *ptr = '\0';
00456     t.tm_min = atoi(before);                       /* get the minutes */
00457     *ptr = ':';
00458   }
00459   else {
00460     t.tm_min = atoi(before);
00461   }
00462       }
00463       else {
00464   free(str);
00465   return (time_t)-1;
00466       }
00467 
00468       if(*ptr == ':') {                                /* seconds following */
00469   before= ptr + 1;                               /* after the seconds, there can only follow the end of
00470               * the string
00471               */
00472   if(!*ptr) return (time_t)0;
00473   t.tm_sec = atoi(before);
00474       }
00475     }
00476   }
00477 
00478   free(str);
00479   return mktime(&t);                                   /* finally, try to generate the timestamp */
00480 }
00481 /* }}} */
00482 
00483 /* {{{ gen_unid
00484  * Returns: int             the length of the generated uid or 0
00485  * Parameters:
00486  *   - u_char *buff          a pointer to a buffer
00487  *   - int maxlen           the maximum length of the id
00488  *
00489  * This function generates a new unique id
00490  *
00491  */
00492 int gen_unid(u_char *buff,int maxlen) {
00493   int i,l;
00494   u_char *remaddr = getenv("REMOTE_ADDR");
00495   static const u_char chars[] = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789_-";
00496   struct timeval  tp;
00497 
00498   if(!remaddr) {
00499     return 0;
00500   }
00501 
00502   if(gettimeofday(&tp,NULL) != 0) {
00503     return 0;
00504   }
00505 
00506   srand(tp.tv_usec);
00507   l = strlen(remaddr);
00508 
00509   if(maxlen > l) {
00510     maxlen = l;
00511   }
00512   if(maxlen <= l) {
00513     l = maxlen - 1;
00514   }
00515 
00516   for(i=0;i<l;i++) {
00517     buff[i] = chars[remaddr[i] % 59 + (unsigned int)(rand() % 3)];
00518   }
00519 
00520   return i;
00521 }
00522 /* }}} */
00523 
00524 #ifdef HAS_NO_GETLINE
00525 /* {{{ getline
00526  * Returns: ssize_t         The number of bytes read or -1 on failure
00527  * Parameters:
00528  *   - u_char **lineptr      The line pointer
00529  *   - size_t *n            The number of bytes allocated
00530  *   - FILE *stream         The stream pointer
00531  *
00532  * This function reads a complete line from FILE *stream.
00533  *
00534  */
00535 ssize_t getline(char **lineptr,size_t *n,FILE *stream) {
00536   return getdelim(lineptr,n,'\n',stream);
00537 }
00538 /* }}} */
00539 #endif
00540 
00541 #ifdef HAS_NO_GETDELIM
00542 /* {{{ getdelim
00543  * Returns: ssize_t         The number of bytes read or -1 on failure
00544  * Parameters:
00545  *   - u_char **lineptr      The line pointer
00546  *   - size_t *n            The number of bytes allocated
00547  *   - int delim            The delimiter character
00548  *   - FILE *stream         The stream pointer
00549  *
00550  * This function reads until 'delim' has been found
00551  *
00552  */
00553 ssize_t getdelim(char **lineptr,size_t *n,int delim,FILE *stream) {
00554   t_string buf;
00555   register u_char c;
00556 
00557   str_init(&buf);
00558 
00559   while(!feof(stream) && !ferror(stream)) {
00560     c = fgetc(stream);
00561     str_char_append(&buf,c);
00562 
00563     if(c == delim) break;
00564   }
00565 
00566   if(*lineptr) free(*lineptr);
00567 
00568   *lineptr = buf.content;
00569   *n       = buf.len;
00570 
00571   if(feof(stream) || ferror(stream)) return -1;
00572 
00573   return buf.len;
00574 }
00575 /* }}} */
00576 #endif
00577 
00578 #ifdef NOSTRDUP
00579 /* {{{ strdup */
00580 u_char *strdup(const u_char *str) {
00581   size_t len = strlen(str);
00582   u_char *buff = fo_alloc(NULL,1,len+1,FO_ALLOC_MALLOC);
00583 
00584   memcpy(buff,str,len+1);
00585 
00586   return buff;
00587 }
00588 /* }}} */
00589 #endif
00590 
00591 #ifdef NOSTRNDUP
00592 /* {{{ strndup */
00593 u_char *strndup(const u_char *str,size_t len) {
00594   u_char *buff = fo_alloc(NULL,1,len+1,FO_ALLOC_MALLOC);
00595 
00596   memcpy(buff,str,len);
00597   buff[len-1] = '\0';
00598 
00599   return buff;
00600 }
00601 /* }}} */
00602 #endif
00603 
00604 /* {{{ Array abstraction */
00605 
00606 void array_init(t_array *ary,size_t element_size,void (*array_destroy)(void *)) {
00607   ary->reserved      = 0;
00608   ary->elements      = 0;
00609   ary->element_size  = element_size;
00610   ary->array         = NULL;
00611   ary->array_destroy = array_destroy;
00612 }
00613 
00614 void array_push(t_array *ary,const void *element) {
00615   if(ary->elements + 1 >= ary->reserved) {
00616     ary->array     = fo_alloc(ary->array,ary->element_size,ary->reserved+1,FO_ALLOC_REALLOC);
00617     ary->reserved += 1;
00618   }
00619 
00620   memcpy(ary->array + (ary->elements * ary->element_size),element,ary->element_size);
00621   ary->elements += 1;
00622 }
00623 
00624 void *array_pop(t_array *ary) {
00625   ary->elements -= 1;
00626   return memdup((void *)(ary->array + ((ary->elements + 1) * ary->element_size)),ary->element_size);
00627 }
00628 
00629 void *array_shift(t_array *ary) {
00630   void *elem = memdup(ary->array,ary->element_size);
00631 
00632   memmove(ary->array,ary->array+ary->element_size,(ary->elements - 1) * ary->element_size);
00633   ary->elements -= 1;
00634   return elem;
00635 }
00636 
00637 void array_unshift(t_array *ary,const void *element) {
00638   if(ary->elements + 1 >= ary->reserved) {
00639     ary->array     = fo_alloc(ary->array,ary->element_size,ary->reserved+1,FO_ALLOC_REALLOC);
00640     ary->reserved += 1;
00641   }
00642 
00643   memmove(ary->array+ary->element_size,ary->array,ary->elements  * ary->element_size);
00644   memcpy(ary->array,element,ary->element_size);
00645   ary->elements += 1;
00646 }
00647 
00648 void array_sort(t_array *ary,int(*compar)(const void *,const void *)) {
00649   qsort(ary->array,ary->elements,ary->element_size,compar);
00650 }
00651 
00652 void *array_bsearch(t_array *ary,const void *key,int (*compar)(const void *, const void *)) {
00653   return bsearch(key,ary->array,ary->elements,ary->element_size,compar);
00654 }
00655 
00656 void *array_element_at(t_array *ary,size_t index) {
00657   if(index < 0 || index > ary->elements) {
00658     errno = EINVAL;
00659     return NULL;
00660   }
00661 
00662   return ary->array + (index * ary->element_size);
00663 }
00664 
00665 void array_destroy(t_array *ary) {
00666  size_t i;
00667 
00668   if(ary->array_destroy) {
00669     for(i=0;i<ary->elements;i++) {
00670       ary->array_destroy(ary->array + (i * ary->element_size));
00671     }
00672   }
00673 
00674   free(ary->array);
00675   memset(ary,0,sizeof(*ary));
00676 }
00677 
00678 /* }}} */
00679 
00680 /* {{{ Tree abstraction */
00686 void cf_tree_rotate_left(t_cf_tree_node **n) {
00687   t_cf_tree_node *tmp = *n;
00688 
00689   *n = (*n)->right;
00690   tmp->right = (*n)->left;
00691   (*n)->left = tmp;
00692 }
00693 
00699 void cf_tree_rotate_right(t_cf_tree_node **n) {
00700   t_cf_tree_node *tmp = *n;
00701 
00702   *n = (*n)->left;
00703   tmp->left = (*n)->right;
00704   (*n)->right = tmp;
00705 }
00706 
00713 int cf_tree_leftgrown(t_cf_tree_node **n) {
00714   switch((*n)->bal) {
00715     case CF_TREE_LEFT:
00716       if((*n)->left->bal == CF_TREE_LEFT) {
00717         (*n)->bal = (*n)->left->bal = CF_TREE_NONE;
00718 
00719         cf_tree_rotate_right(n);
00720       }
00721       else {
00722         switch((*n)->left->right->bal) {
00723           case CF_TREE_LEFT:
00724             (*n)->bal = CF_TREE_RIGHT;
00725             (*n)->left->bal = CF_TREE_NONE;
00726             break;
00727 
00728           case CF_TREE_RIGHT:
00729             (*n)->bal       = CF_TREE_NONE;
00730             (*n)->left->bal = CF_TREE_LEFT;
00731             break;
00732 
00733           default:
00734             (*n)->bal = CF_TREE_NONE;
00735             (*n)->left->bal = CF_TREE_NONE;
00736         }
00737 
00738         (*n)->left->right->bal = CF_TREE_NONE;
00739 
00740         cf_tree_rotate_left(&(*n)->left);
00741         cf_tree_rotate_right(n);
00742       }
00743 
00744       return 0;
00745 
00746     case CF_TREE_RIGHT:
00747       (*n)->bal = CF_TREE_NONE;
00748       return 0;
00749 
00750     default:
00751       (*n)->bal = CF_TREE_LEFT;
00752       return 1;
00753   }
00754 }
00755 
00762 int cf_tree_rightgrown(t_cf_tree_node **n) {
00763   switch((*n)->bal) {
00764     case CF_TREE_LEFT:
00765       (*n)->bal = CF_TREE_NONE;
00766       return 0;
00767 
00768     case CF_TREE_RIGHT:
00769       if((*n)->right->bal == CF_TREE_RIGHT) {
00770         (*n)->bal = (*n)->right->bal = CF_TREE_NONE;
00771         cf_tree_rotate_left(n);
00772       }
00773       else {
00774         switch((*n)->right->left->bal) {
00775           case CF_TREE_RIGHT:
00776             (*n)->bal = CF_TREE_LEFT;
00777             (*n)->right->bal = CF_TREE_NONE;
00778             break;
00779 
00780           case CF_TREE_LEFT:
00781             (*n)->bal = CF_TREE_NONE;
00782             (*n)->right->bal = CF_TREE_RIGHT;
00783             break;
00784 
00785           default:
00786             (*n)->bal = CF_TREE_NONE;
00787             (*n)->right->bal = CF_TREE_NONE;
00788         }
00789 
00790         (*n)->right->left->bal = CF_TREE_NONE;
00791         cf_tree_rotate_right(& (*n)->right);
00792         cf_tree_rotate_left(n);
00793       }
00794 
00795       return 0;
00796 
00797     default:
00798       (*n)->bal = CF_TREE_RIGHT;
00799       return 1;
00800   }
00801 }
00802 
00803 
00804 int cf_tree_insert(t_cf_tree *tree,t_cf_tree_node **n, t_cf_tree_dataset *d) {
00805   int tmp;
00806 
00807   if(!n) n = &tree->root;
00808 
00809   if(!(*n)) {
00810     *n = fo_alloc(NULL,1,sizeof(*tree->root),FO_ALLOC_CALLOC);
00811 
00812     (*n)->d   = memdup(d,sizeof(*d));
00813     (*n)->bal = 0;
00814 
00815     return 1;
00816   }
00817 
00818   if(tree->compare(d,(*n)->d) < 0) {
00819     if((tmp = cf_tree_insert(tree,&(*n)->left,d)) == 1) {
00820       return cf_tree_leftgrown(n);
00821     }
00822 
00823     return tmp;
00824   }
00825   else if(tree->compare(d,(*n)->d) > 0) {
00826     if((tmp = cf_tree_insert(tree,&(*n)->right,d)) == 1) {
00827       return cf_tree_rightgrown(n);
00828     }
00829 
00830     return tmp;
00831   }
00832 
00833   return -1;
00834 }
00835 
00842 int cf_tree_leftshrunk(t_cf_tree_node **n) {
00843   switch((*n)->bal) {
00844     case CF_TREE_LEFT:
00845       (*n)->bal = CF_TREE_NONE;
00846 
00847       return 1;
00848 
00849     case CF_TREE_RIGHT:
00850       if((*n)->right->bal == CF_TREE_RIGHT) {
00851         (*n)->bal = (*n)->right->bal = CF_TREE_NONE;
00852         cf_tree_rotate_left(n);
00853 
00854         return 1;
00855       }
00856       else if((*n)->right->bal == CF_TREE_NONE) {
00857         (*n)->bal = CF_TREE_RIGHT;
00858         (*n)->right->bal = CF_TREE_LEFT;
00859         cf_tree_rotate_left(n);
00860 
00861         return 0;
00862       }
00863       else {
00864         switch((*n)->right->left->bal) {
00865           case CF_TREE_LEFT:
00866             (*n)->bal = CF_TREE_NONE;
00867             (*n)->right->bal = CF_TREE_RIGHT;
00868             break;
00869 
00870           case CF_TREE_RIGHT:
00871             (*n)->bal = CF_TREE_LEFT;
00872             (*n)->right->bal = CF_TREE_NONE;
00873             break;
00874 
00875           default:
00876             (*n)->bal = CF_TREE_NONE;
00877             (*n)->right->bal = CF_TREE_NONE;
00878         }
00879 
00880         (*n)->right->left->bal = CF_TREE_NONE;
00881         cf_tree_rotate_right(&(*n)->right);
00882         cf_tree_rotate_left(n);
00883         return 1;
00884       }
00885 
00886     default:
00887       (*n)->bal = CF_TREE_RIGHT;
00888       return 0;
00889   }
00890 }
00891 
00898 int cf_tree_rightshrunk(t_cf_tree_node **n) {
00899   switch((*n)->bal) {
00900     case CF_TREE_RIGHT:
00901       (*n)->bal = CF_TREE_NONE;
00902       return 1;
00903 
00904     case CF_TREE_LEFT:
00905       if((*n)->left->bal == CF_TREE_LEFT) {
00906         (*n)->bal = (*n)->left->bal = CF_TREE_NONE;
00907         cf_tree_rotate_right(n);
00908 
00909         return 1;
00910       }
00911       else if((*n)->left->bal == CF_TREE_NONE) {
00912         (*n)->bal = CF_TREE_LEFT;
00913         (*n)->left->bal = CF_TREE_RIGHT;
00914         cf_tree_rotate_right(n);
00915 
00916         return 0;
00917       }
00918       else {
00919         switch((*n)->left->right->bal) {
00920           case CF_TREE_LEFT:
00921             (*n)->bal = CF_TREE_RIGHT;
00922             (*n)->left->bal = CF_TREE_NONE;
00923             break;
00924 
00925           case CF_TREE_RIGHT:
00926             (*n)->bal = CF_TREE_NONE;
00927             (*n)->left->bal = CF_TREE_LEFT;
00928             break;
00929 
00930           default:
00931             (*n)->bal = CF_TREE_NONE;
00932             (*n)->left->bal = CF_TREE_NONE;
00933         }
00934 
00935         (*n)->left->right->bal = CF_TREE_NONE;
00936 
00937         cf_tree_rotate_left(&(*n)->left);
00938         cf_tree_rotate_right(n);
00939 
00940         return 1;
00941       }
00942 
00943     default:
00944       (*n)->bal = CF_TREE_LEFT;
00945       return 0;
00946   }
00947 }
00948 
00956 int cf_tree_findhighest(t_cf_tree_node *target,t_cf_tree_node **n,int *res) {
00957   t_cf_tree_node *tmp;
00958 
00959   *res = 1;
00960   if(!(*n)) {
00961     return 0;
00962   }
00963 
00964   if((*n)->right) {
00965     if(!cf_tree_findhighest(target,&(*n)->right,res)) {
00966       return 0;
00967     }
00968     if(*res == 1) {
00969       *res = cf_tree_rightshrunk(n);
00970     }
00971 
00972     return 1;
00973   }
00974 
00975   target->d = (*n)->d;
00976   tmp = *n;
00977   *n = (*n)->left;
00978   free(tmp);
00979 
00980   return 1;
00981 }
00982 
00990 int cf_tree_findlowest(t_cf_tree_node *target,t_cf_tree_node **n,int *res) {
00991   t_cf_tree_node *tmp;
00992 
00993   *res = 1;
00994   if(!(*n)) return 0;
00995 
00996   if((*n)->left) {
00997     if(!cf_tree_findlowest(target,&(*n)->left,res)) {
00998       return 0;
00999     }
01000     if(*res == 1) {
01001       *res = cf_tree_leftshrunk(n);
01002     }
01003 
01004     return 1;
01005   }
01006 
01007   target->d = (*n)->d;
01008   tmp = *n;
01009   *n = (*n)->right;
01010   free(tmp);
01011 
01012   return 1;
01013 }
01014 
01015 int cf_tree_remove(t_cf_tree *tree,t_cf_tree_node **n,t_cf_tree_dataset *key) {
01016   int tmp = 1;
01017 
01018   if(!n) n = &tree->root;
01019 
01020   if(!(*n)) return -1;
01021 
01022   if(tree->compare(key,(*n)->d) < 0) {
01023     if((tmp = cf_tree_remove(tree,&(*n)->left, key)) == 1) {
01024       return cf_tree_leftshrunk(n);
01025     }
01026 
01027     return tmp;
01028   }
01029   else if(tree->compare(key, (*n)->d) > 0) {
01030     if((tmp = cf_tree_remove(tree,&(*n)->right,key)) == 1) {
01031       return cf_tree_rightshrunk(n);
01032     }
01033 
01034     return tmp;
01035   }
01036 
01037   if((*n)->left) {
01038     if(cf_tree_findhighest(*n, &((*n)->left), &tmp)) {
01039       if(tmp == 1) {
01040         tmp = cf_tree_leftshrunk(n);
01041       }
01042 
01043       return tmp;
01044     }
01045   }
01046   if((*n)->right) {
01047     if(cf_tree_findlowest(*n, &((*n)->right), &tmp)) {
01048       if(tmp == 1) {
01049         tmp = cf_tree_rightshrunk(n);
01050       }
01051       return tmp;
01052     }
01053   }
01054 
01055   free(*n);
01056   *n = NULL;
01057 
01058   return 1;
01059 }
01060 
01061 const t_cf_tree_dataset *cf_tree_find(t_cf_tree *tree,t_cf_tree_node *n, t_cf_tree_dataset *key) {
01062 
01063   if(!n) return NULL;
01064 
01065   if(tree->compare(key,n->d) < 0) {
01066     return cf_tree_find(tree,n->left,key);
01067   }
01068   else if(tree->compare(key,n->d) > 0) {
01069     return cf_tree_find(tree,n->right,key);
01070   }
01071 
01072   return n->d;
01073 }
01074 
01075 void cf_tree_init(t_cf_tree *tree,int (*compare)(t_cf_tree_dataset *,t_cf_tree_dataset *),void (*destroy)(t_cf_tree_dataset *)) {
01076   tree->root    = NULL;
01077   tree->compare = compare;
01078   tree->destroy = destroy;
01079 }
01080 
01086 void cf_tree_destroy_nodes(t_cf_tree *tree,t_cf_tree_node *n) {
01087   if(n) {
01088     if(n->left) cf_tree_destroy_nodes(tree,n->left);
01089     if(n->right) cf_tree_destroy_nodes(tree,n->right);
01090 
01091     if(tree->destroy) {
01092       tree->destroy(n->d);
01093     }
01094     else {
01095       if(n->d->key)  free(n->d->key);
01096       if(n->d->data) free(n->d->data);
01097     }
01098 
01099     free(n->d);
01100     free(n);
01101   }
01102 }
01103 
01104 void cf_tree_destroy(t_cf_tree *tree) {
01105   cf_tree_destroy_nodes(tree,tree->root);
01106 }
01107 
01108 /* }}} */
01109 
01110 /* {{{ Faster implementation of the string comparing functions */
01111 
01112 int cf_strcmp(const u_char *str1,const u_char *str2) {
01113   register u_char *ptr1 = (u_char *)str1;
01114   register u_char *ptr2 = (u_char *)str2;
01115 
01116   for(;*ptr1 && *ptr2 && *ptr1 == *ptr2;ptr1++,ptr2++);
01117 
01118   if(*ptr1 == *ptr2) return 0;
01119 
01120   return 1;
01121 }
01122 
01123 int cf_strcasecmp(const u_char *str1,const u_char *str2) {
01124   register u_char *ptr1 = (u_char *)str1;
01125   register u_char *ptr2 = (u_char *)str2;
01126 
01127   for(;*ptr1 && *ptr2 && toupper(*ptr1) == toupper(*ptr2);ptr1++,ptr2++);
01128 
01129   if(toupper(*ptr1) == toupper(*ptr2)) return 0;
01130 
01131   return 1;
01132 }
01133 
01134 int cf_strncmp(const u_char *str1,const u_char *str2,size_t n) {
01135   register u_char *ptr1 = (u_char *)str1;
01136   register u_char *ptr2 = (u_char *)str2;
01137   register size_t i;
01138 
01139   for(i=0;*ptr1 && *ptr2 && *ptr1 == *ptr2 && i < n;ptr1++,ptr2++,i++) {
01140     if(i == n - 1) return 0;
01141   }
01142 
01143   return 1;
01144 }
01145 
01146 int cf_strncasecmp(const u_char *str1,const u_char *str2,size_t n) {
01147   register u_char *ptr1 = (u_char *)str1;
01148   register u_char *ptr2 = (u_char *)str2;
01149   register size_t i;
01150 
01151   for(i=0;*ptr1 && *ptr2 && i < n && toupper(*ptr1) == toupper(*ptr2);ptr1++,ptr2++,i++) {
01152     if(i == n - 1) return 0;
01153   }
01154 
01155   return 1;
01156 }
01157 
01158 size_t cf_strlen_utf8(const u_char *str,size_t rlen) {
01159   register size_t len;
01160   register u_char *ptr;
01161   int bytes;
01162   u_int32_t num;
01163 
01164   for(ptr=(u_char *)str;*ptr;len++) {
01165     if((bytes = utf8_to_unicode(ptr,rlen,&num)) < 0) {
01166       return -1;
01167     }
01168 
01169     ptr  += bytes;
01170     rlen -= bytes;
01171   }
01172 
01173   return rlen;
01174 }
01175 
01176 /* }}} */
01177 
01178 /* eof */

Generated on Sun Apr 25 16:37:39 2004 for Classic Forum by doxygen 1.3.5