Author: leo
Date: Thu Aug 4 02:29:52 2005
New Revision: 8805
Modified:
trunk/src/string.c
trunk/t/op/stringu.t
Log:
fix substr bug #36794; fix test
Modified: trunk/src/string.c
==============================================================================
--- trunk/src/string.c (original)
+++ trunk/src/string.c Thu Aug 4 02:29:52 2005
@@ -1148,20 +1148,19 @@ string_replace(Interp *interpreter, STRI
INTVAL offset, INTVAL length, STRING *rep, STRING **d)
{
STRING *dest = NULL;
- UINTVAL substart_off; /* Offset from start of string to our
- * piece */
- UINTVAL subend_off; /* Offset from start of string to the
- * end of our piece */
+ UINTVAL start_byte, end_byte;
UINTVAL true_offset;
UINTVAL true_length;
INTVAL diff;
CHARSET *cs;
+ ENCODING *enc;
+ String_iter iter;
true_offset = (UINTVAL)offset;
true_length = (UINTVAL)length;
/* may have different reps..... */
- if ( !(cs = string_rep_compatible(interpreter, src, rep, NULL))) {
+ if ( !(cs = string_rep_compatible(interpreter, src, rep, &enc))) {
internal_exception(UNIMPLEMENTED,
"Cross-type string replace (%s/%s) (%s/%s) unsupported",
((ENCODING *)(src->encoding))->name,
@@ -1187,61 +1186,58 @@ string_replace(Interp *interpreter, STRI
true_length = (UINTVAL)(src->strlen - true_offset);
}
+ /* get byte position of the part that will be replaced */
+ ENCODING_ITER_INIT(interpreter, src, &iter);
+ iter.set_position(interpreter, &iter, true_offset);
+ start_byte = iter.bytepos;
+ iter.set_position(interpreter, &iter, true_offset + true_length);
+ end_byte = iter.bytepos;
+ /* not possible.... */
+ if (end_byte < start_byte) {
+ internal_exception(SUBSTR_OUT_OF_STRING,
+ "replace: subend somehow is less than substart");
+ }
/* Save the substring that is replaced for the return value */
-
if (d != NULL) {
UINTVAL length_bytes = string_max_bytes(interpreter, src, true_length);
- dest = string_make_empty(interpreter, enum_stringrep_one, true_length);
+ dest = string_make_empty(interpreter, enum_stringrep_one,
length_bytes);
dest->charset = src->charset;
dest->encoding = src->encoding;
mem_sys_memcopy(dest->strstart,
- (char *)src->strstart
- + string_max_bytes(interpreter, src, true_offset),
- length_bytes);
+ (char *)src->strstart + start_byte,
+ end_byte - start_byte);
- dest->bufused = length_bytes;
+ dest->bufused = end_byte - start_byte;
dest->strlen = true_length;
*d = dest;
}
src->charset = cs;
+ src->encoding = enc;
/* Now do the replacement */
-
- /* XXXX: make sure the rest of this method is correct, vis-a-vis byte v.
- character */
- substart_off = string_max_bytes(interpreter, src, true_offset);
-
- subend_off = substart_off + string_max_bytes(interpreter, src,
true_length);
-
- /* not possible.... */
- if (subend_off < substart_off) {
- internal_exception(SUBSTR_OUT_OF_STRING,
- "replace: subend somehow is less than substart");
- }
-
/*
* If the replacement string fits inside the original substring
* don't create a new string, just pack it.
*/
- diff = (subend_off - substart_off) - rep->bufused;
+ diff = (end_byte - start_byte) - rep->bufused;
if(diff >= 0
|| ((INTVAL)src->bufused - (INTVAL)PObj_buflen(src)) <= diff) {
Parrot_unmake_COW(interpreter, src);
if(diff != 0) {
- mem_sys_memmove((char*)src->strstart + substart_off + rep->bufused,
- (char*)src->strstart + subend_off,
- src->bufused - subend_off);
+ mem_sys_memmove((char*)src->strstart + start_byte + rep->bufused,
+ (char*)src->strstart + end_byte,
+ src->bufused - end_byte);
src->bufused -= diff;
}
- mem_sys_memcopy((char*)src->strstart + substart_off,
+ mem_sys_memcopy((char*)src->strstart + start_byte,
rep->strstart, rep->bufused);
if(diff != 0)
(void)string_compute_strlen(interpreter, src);
@@ -1256,11 +1252,11 @@ string_replace(Interp *interpreter, STRI
/* Move the end of old string that isn't replaced to new offset
* first */
- mem_sys_memmove((char*)src->strstart + subend_off + diff,
- (char*)src->strstart + subend_off,
- src->bufused - subend_off);
+ mem_sys_memmove((char*)src->strstart + end_byte + diff,
+ (char*)src->strstart + end_byte,
+ src->bufused - end_byte);
/* Copy the replacement in */
- mem_sys_memcopy((char *)src->strstart + substart_off, rep->strstart,
+ mem_sys_memcopy((char *)src->strstart + start_byte, rep->strstart,
rep->bufused);
src->bufused += diff;
(void)string_compute_strlen(interpreter, src);
Modified: trunk/t/op/stringu.t
==============================================================================
--- trunk/t/op/stringu.t (original)
+++ trunk/t/op/stringu.t Thu Aug 4 02:29:52 2005
@@ -203,18 +203,15 @@ CODE
/Malformed string/
OUTPUT
-#TODO: {
-#local $TODO = "bug #36794";
-
-output_is( <<'CODE', <<OUTPUT, "substr with a UTF8 replacement" );
- set S0, "\\u666"
+output_is( <<'CODE', <<OUTPUT, "substr with a UTF8 replacement #36794" );
+ set S0, "AAAAAAAAAA\\u666"
set I0, 0x666
- chr S1, I0
- substr S0, 0, 5, S1
+ chr S1, I0
+ substr S0, 10, 5, S1
print S0
print "\n"
+ end
CODE
-\x{666}
+AAAAAAAAAA\xd9\xa6
OUTPUT
-#}