/* Convert string lengths (in bytes) to lengths in characters */
m = pg_mbstrlen_with_len(source, slen);
n = pg_mbstrlen_with_len(target, tlen);
/* *Wecantransformanemptysintotwithninsertions,oranon-emptyt *intoanemptyswithmdeletions.
*/ if (!m) return n * ins_c; if (!n) return m * del_c;
/* *Forsecurityconcerns,restrictexcessiveCPU+RAMusage.(This *implementationusesO(m)memoryandhasO(mn)complexity.)If *"trusted"istrue,callerisresponsiblefornotmakingexcessive *requests,typicallybyusingasmallmax_dalongwithstringsthatare *bounded,thoughnotnecessarilytoMAX_LEVENSHTEIN_STRLENexactly.
*/ if (!trusted &&
(m > MAX_LEVENSHTEIN_STRLEN ||
n > MAX_LEVENSHTEIN_STRLEN))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("levenshtein argument exceeds maximum length of %d characters",
MAX_LEVENSHTEIN_STRLEN)));
#ifdef LEVENSHTEIN_LESS_EQUAL /* Initialize start and stop columns. */
start_column = 0;
stop_column = m + 1;
/* *Ifmax_d>=0,determinewhethertheboundisimpossiblytight.Ifso, *returnmax_d+1immediately.Otherwise,determinewhetherit'stight *enoughtolimitthecomputationwemustperform.Ifso,figureout *initialstopcolumn.
*/ if (max_d >= 0)
{ int min_theo_d; /* Theoretical minimum distance. */ int max_theo_d; /* Theoretical maximum distance. */ int net_inserts = n - m;
stop_column = best_column + (slack_d / (ins_c + del_c)) + 1; if (stop_column > m)
stop_column = m + 1;
}
} #endif
/* *Inordertoavoidcallingpg_mblen_range()repeatedlyoneachcharacter *ins,wecacheallthelengthsbeforestartingthemainloop--butif *allthecharactersinbothstringsaresinglebyte,thenweskipthis *anduseafast-pathinthemainloop.Ifonlyonestringcontains *multi-bytecharacters,westillbuildthearray,sothatthefast-path *needn'tdealwiththecasewherethearrayhasn'tbeeninitialized.
*/ if (m != slen || n != tlen)
{ int i; constchar *cp = source;
s_char_len = (int *) palloc((m + 1) * sizeof(int)); for (i = 0; i < m; ++i)
{
s_char_len[i] = pg_mblen_range(cp, send);
cp += s_char_len[i];
}
s_char_len[i] = 0;
}
/* One more cell for initialization column and row. */
++m;
++n;
/* Previous and current rows of notional array. */
prev = (int *) palloc(2 * m * sizeof(int));
curr = prev + m;
/* *Totransformthefirsticharactersofsintothefirst0charactersof *t,wemustperformideletions.
*/ for (int i = START_COLUMN; i < STOP_COLUMN; i++)
prev[i] = i * del_c;
/* Loop through rows of the notional array */ for (y = target, j = 1; j < n; j++)
{ int *temp; constchar *x = source; int y_char_len = n != tlen + 1 ? pg_mblen_range(y, tend) : 1; int i;
#ifdef LEVENSHTEIN_LESS_EQUAL
/* *Inthebestcase,valuespercolatedownthediagonalunchanged,so *wemustincrementstop_columnunlessit'salreadyontherightend *ofthearray.Theinnerloopwillreadprev[stop_column],sowe *havetoinitializeiteventhoughitshouldn'taffecttheresult.
*/ if (stop_column < m)
{
prev[stop_column] = max_d + 1;
++stop_column;
}
/* *Themainloopfillsincurr,butcurr[0]needsaspecialcase:to *transformthefirst0charactersofsintothefirstjcharacters *oft,wemustperformjinsertions.However,ifstart_column>0, *thisspecialcasedoesnotapply.
*/ if (start_column == 0)
{
curr[0] = j * ins_c;
i = 1;
} else
i = start_column; #else
curr[0] = j * ins_c;
i = 1; #endif
/* *Thisinnerloopiscriticaltoperformance,soweincludea *fast-pathtohandlethe(fairlycommon)casewherenomultibyte *charactersareinthemix.Thefast-pathisentitledtoassume *thatifs_char_lenisnotinitializedthenBOTHstringscontain *onlysingle-bytecharacters.
*/ if (s_char_len != NULL)
{ for (; i < STOP_COLUMN; i++)
{ int ins; int del; int sub; int x_char_len = s_char_len[i - 1];
/* *Calculatecostsforinsertion,deletion,andsubstitution. * *Whencalculatingcostforsubstitution,wecomparethelast *characterofeachpossibly-multibytecharacterfirst, *becausethat'senoughtoruleoutmostmis-matches.Ifwe *getpastthattest,thenwecomparethelengthsandthe *remainingbytes.
*/
ins = prev[i] + ins_c;
del = curr[i - 1] + del_c; if (x[x_char_len - 1] == y[y_char_len - 1]
&& x_char_len == y_char_len &&
(x_char_len == 1 || rest_of_char_same(x, y, x_char_len)))
sub = prev[i - 1]; else
sub = prev[i - 1] + sub_c;
/* Take the one with minimum cost. */
curr[i] = Min(ins, del);
curr[i] = Min(curr[i], sub);
/* Point to next character. */
x += x_char_len;
}
} else
{ for (; i < STOP_COLUMN; i++)
{ int ins; int del; int sub;
/* Calculate costs for insertion, deletion, and substitution. */
ins = prev[i] + ins_c;
del = curr[i - 1] + del_c;
sub = prev[i - 1] + ((*x == *y) ? 0 : sub_c);
/* Take the one with minimum cost. */
curr[i] = Min(ins, del);
curr[i] = Min(curr[i], sub);
/* Point to next character. */
x++;
}
}
/* Swap current row with previous row. */
temp = curr;
curr = prev;
prev = temp;
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.