pike.git/
src/
builtin_functions.c
Branch:
Tag:
Non-build tags
All tags
No tags
2006-03-11
2006-03-11 12:31:35 by Henrik Grubbström (Grubba) <grubba@grubba.org>
24e45ce6dd81943e9e63a8ab5e9c463aa0938c82 (
135
lines) (+
92
/-
43
)
[
Show
|
Annotate
]
Branch:
7.9
replace_many() now actually works for zero-length strings...
Rev: src/builtin_functions.c:1.612
2:
|| This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
-
|| $Id: builtin_functions.c,v 1.
611
2006/03/
10
19
:
59
:
22
grubba Exp $
+
|| $Id: builtin_functions.c,v 1.
612
2006/03/
11
12
:
31
:
35
grubba Exp $
*/ #include "global.h"
3272:
struct tupel { int prefix;
+
int is_prefix;
struct pike_string *ind; struct pike_string *val; };
3293:
INT32 a, INT32 b) {
-
INT32 c,match=-1, match_len=
0
, d;
+
INT32 c,
match=-1, match_len=
-1
, d;
ptrdiff_t tmp; check_c_stack(2048);
3302:
{ c=(a+b)/2;
+
#if 1
+
if (v[c].ind->len <= match_len) {
+
/* Can't be a suffix of (or is equal to) the current match. */
+
b = c;
+
continue;
+
}
+
#endif
+
tmp=generic_find_binary_prefix(v[c].ind->str, v[c].ind->len, v[c].ind->size_shift,
3312:
if(tmp<0) { int d;
+
/* Check if we might have a valid prefix that is better than * the current match. */ if (~tmp > match_len) {
3335:
} else {
+
if (!v[c].is_prefix) {
+
return c;
+
}
a=c+1; /* There might still be a better match... */ match=c; match_len = v[c].ind->len;
3369:
ptrdiff_t s, length; struct replace_many_context ctx; ONERROR uwp;
+
struct pike_string *empty_repl = NULL;
int set_start[256]; int set_end[256];
-
+
int other_start;
if(from->size != to->size) Pike_error("Replace must have equal-sized from and to arrays.\n");
3411:
if(ITEM(from)[e].u.string->size_shift > str->size_shift) continue;
+
if (!ITEM(from)[e].u.string->len) {
+
if (ITEM(to)[e].u.string->len) {
+
empty_repl = ITEM(to)[e].u.string;
+
}
+
continue;
+
}
+
ctx.v[num].ind=ITEM(from)[e].u.string; ctx.v[num].val=ITEM(to)[e].u.string; ctx.v[num].prefix=-2; /* Uninitialized */
-
+
ctx.v[num].is_prefix=0;
num++; }
3421:
MEMSET(set_start, 0, sizeof(set_start)); MEMSET(set_end, 0, sizeof(set_end));
+
other_start = num;
for(e=0;e<num;e++) {
-
INT32
x;
+
{
+
p_wchar2
x;
-
+
if (ctx.v[num-1-e].ind->len) {
x=index_shared_string(ctx.v[num-1-e].ind,0);
-
if(
(
x<
(INT32)
NELEM(set_start))
&& (x >= 0))
+
if
(x<NELEM(set_start))
set_start[x]=num-e-1;
-
+
else
+
other_start = num-e-1;
+
}
-
+
if (ctx.v[e].ind->len) {
x=index_shared_string(ctx.v[e].ind,0);
-
if(
(
x<
(INT32)
NELEM(set_end))
&& (x >= 0))
+
if
(x<NELEM(set_end))
set_end[x]=e+1;
-
-
x
= e-1;
-
if (
x
>= 0) {
-
ptrdiff_t tmp = generic_find_binary_prefix(ctx.v[e].ind->str,
+
}
+
}
+
{
+
INT32 prefix
= e-1;
+
if (
prefix
>= 0) {
+
ptrdiff_t tmp =
+
generic_find_binary_prefix(ctx.v[e].ind->str,
ctx.v[e].ind->len, ctx.v[e].ind->size_shift,
-
ctx.v[
x
].ind->str,
-
ctx.v[
x
].ind->len,
-
ctx.v[
x
].ind->size_shift);
+
ctx.v[
prefix
].ind->str,
+
ctx.v[
prefix
].ind->len,
+
ctx.v[
prefix
].ind->size_shift);
if (!tmp) {
-
/* ctx.v[
x
] is a valid prefix to ctx.v[e]. */
+
/* ctx.v[
prefix
] is a valid prefix to ctx.v[e]. */
} if (tmp == 1) { /* Optimization. */
-
x
= -1;
+
prefix
= -1;
} else { #ifdef PIKE_DEBUG if (tmp < 0) Pike_fatal("Sorting with replace_sortfunc failed.\n");
3455:
/* Find the first prefix that is shorter than the point at which * the initial strings differed. */
-
while (
x
>= 0) {
-
if (ctx.v[
x
].ind->len < tmp) break;
-
x
= ctx.v[
x
].prefix;
+
while (
prefix
>= 0) {
+
if (ctx.v[
prefix
].ind->len < tmp) break;
+
prefix
= ctx.v[
prefix
].prefix;
} }
-
+
if (prefix >= 0) {
+
ctx.v[prefix].is_prefix = 1;
}
-
ctx.v[e].prefix = x;
+
}
-
+
ctx.v[e].prefix = prefix;
+
}
+
}
length=str->len;
3471:
for(e = s = 0;length > 0;) { INT32 a,b;
-
ptrdiff
_
t
ch;
+
p
_
wchar2
ch;
ch=index_shared_string(str,s);
-
if(
(
ch<
(ptrdiff_t)
NELEM(set_end))
&& (ch >= 0))
+
if(ch<NELEM(set_end))
{
b=set_end[ch];
-
else
+
if (!b) goto next_char;
+
a=set_start[ch];
+
}
else
{
b=num;
-
+
a=other_start;
+
}
+
if (a >= b) goto next_char;
-
if(b)
+
{
-
if((ch<(ptrdiff_t)NELEM(set_start)) && (ch >= 0))
-
a=set_start[ch];
-
else
-
a=0;
-
+
a=find_longest_prefix(str->str+(s << str->size_shift), length, str->size_shift,
3507:
} } ch = ctx.v[a].ind->len;
-
if(!ch) ch=1;
+
s+=ch; length-=ch;
-
string_builder_shared_strcat(&ctx.ret,ctx.v[a].val);
+
e = s;
-
+
string_builder_shared_strcat(&ctx.ret,ctx.v[a].val);
+
if (empty_repl && length) {
+
/* Append the replacement for the empty string too. */
+
string_builder_shared_strcat(&ctx.ret, empty_repl);
+
}
continue; } }
-
+
next_char:
s++; length--;
-
+
if (empty_repl && length) {
+
/* We have a replace with the empty string,
+
* and we're not on the last character in the source string.
+
*/
+
string_builder_putchar(&ctx.ret, ch);
+
string_builder_shared_strcat(&ctx.ret, empty_repl);
+
e = s;
}
-
+
}
if (e < s) { switch(str->size_shift) { case 0: