/* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Hartmut Holzgraefe | +----------------------------------------------------------------------+ */ /* $Id$ */ #include "php.h" #include #include #include #include "php_string.h" /* faster, but obfuscated, all operations have a cost of 1 */ static int fastest_levdist(const char *s1, const char *s2) { register char *p1,*p2; register int i,j,n; int l1=0,l2=0; char r[512]; const char *tmp; /* skip equal start sequence, if any */ while(*s1==*s2) { if(!*s1) break; s1++; s2++; } /* if we already used up one string, then the result is the length of the other */ if(*s1=='\0') return strlen(s2); if(*s2=='\0') return strlen(s1); /* length count */ while(*s1++) l1++; while(*s2++) l2++; /* cut of equal tail sequence, if any */ while(*--s1 == *--s2) { l1--; l2--; } /* reset pointers, adjust length */ s1-=l1++; s2-=l2++; /* possible dist to great? */ if(abs(l1-l2)>=255) return -1; /* swap if l2 longer than l1 */ if(l1=255) return -1; /* swap if l2 longer than l1 */ if(l1value.str.val, (*str2)->value.str.val); break; case 5: /* more general version: calc cost by ins/rep/del weights */ if (zend_get_parameters_ex(5, &str1, &str2, &cost_ins, &cost_rep, &cost_del) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(str1); convert_to_string_ex(str2); convert_to_long_ex(cost_ins); convert_to_long_ex(cost_rep); convert_to_long_ex(cost_del); distance = weighted_levdist((*str1)->value.str.val , (*str2)->value.str.val , (*cost_ins)->value.lval , (*cost_rep)->value.lval , (*cost_del)->value.lval ); break; case 3: /* most general version: calc cost by user-supplied function */ if (zend_get_parameters_ex(3, &str1, &str2, &callback_name) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string_ex(str1); convert_to_string_ex(str2); convert_to_string_ex(callback_name); distance = custom_levdist((*str1)->value.str.val , (*str2)->value.str.val , (*callback_name)->value.str.val ); break; default: WRONG_PARAM_COUNT; } if(distance<0) { php_error(E_WARNING,"levenshtein(): argument string(s) too long"); } RETURN_LONG(distance); } /* }}} */