From 2b888e46f63e90ec2b21eedc1926e2a30703b837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Tue, 29 Jan 2008 21:10:06 +0100 Subject: [PATCH] reverse() now supports reversals of sub-ranges. Rev: src/array.c:1.199 Rev: src/array.h:1.72 Rev: src/builtin_functions.c:1.651 --- src/array.c | 31 ++++++++++---- src/array.h | 4 +- src/builtin_functions.c | 89 +++++++++++++++++++++++++++++++---------- 3 files changed, 92 insertions(+), 32 deletions(-) diff --git a/src/array.c b/src/array.c index e6d1172adb..bf575cad99 100644 --- a/src/array.c +++ b/src/array.c @@ -2,7 +2,7 @@ || 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: array.c,v 1.198 2008/01/26 22:34:17 mast Exp $ +|| $Id: array.c,v 1.199 2008/01/29 20:10:06 grubba Exp $ */ #include "global.h" @@ -2476,20 +2476,29 @@ PMOD_EXPORT void apply_array(struct array *a, INT32 args) * reference, the array will be reversed into a new array. Otherwise * the array will be destructively reversed in place. */ -PMOD_EXPORT struct array *reverse_array(struct array *a) +PMOD_EXPORT struct array *reverse_array(struct array *a, int start, int end) { INT32 e; struct array *ret; + if ((end <= start) || (start >= a->size)) { + add_ref(a); + return a; + } + if (end >= a->size) { + end = a->size; + } else { + end++; + } + if(a->refs == 1) /* Reverse in-place. */ { struct svalue *tmp0, *tmp1, swap; - tmp0 = ITEM(a); - tmp1 = ITEM(a) + a->size; - for(e = a->size>>1; 0 < e; e--) - { + tmp0 = ITEM(a) + start; + tmp1 = ITEM(a) + end; + while (tmp0 < tmp1) { swap = *tmp0; *(tmp0++) = *(--tmp1); *tmp1 = swap; @@ -2500,10 +2509,16 @@ PMOD_EXPORT struct array *reverse_array(struct array *a) add_ref(a); return a; } + + // fprintf(stderr, "R"); ret=allocate_array_no_init(a->size,0); - for(e=0;e<a->size;e++) - assign_svalue_no_free(ITEM(ret)+e,ITEM(a)+a->size+~e); + for(e=0;e<start;e++) + assign_svalue_no_free(ITEM(ret)+e,ITEM(a)+e); + for(;e<end;e++) + assign_svalue_no_free(ITEM(ret)+e,ITEM(a)+end+~e-start); + for(;e<a->size;e++) + assign_svalue_no_free(ITEM(ret)+e,ITEM(a)+e); ret->type_field = a->type_field; return ret; } diff --git a/src/array.h b/src/array.h index 34e1b3e86d..6cecae9e7b 100644 --- a/src/array.h +++ b/src/array.h @@ -2,7 +2,7 @@ || 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: array.h,v 1.71 2008/01/26 22:34:17 mast Exp $ +|| $Id: array.h,v 1.72 2008/01/29 20:10:06 grubba Exp $ */ #ifndef ARRAY_H @@ -184,7 +184,7 @@ PMOD_EXPORT struct pike_string *implode(struct array *a,struct pike_string *del) PMOD_EXPORT struct array *copy_array_recursively(struct array *a, struct mapping *p); PMOD_EXPORT void apply_array(struct array *a, INT32 args); -PMOD_EXPORT struct array *reverse_array(struct array *a); +PMOD_EXPORT struct array *reverse_array(struct array *a, int start, int end); void array_replace(struct array *a, struct svalue *from, struct svalue *to); diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 4403aa161e..71aed750e9 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -2,7 +2,7 @@ || 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.650 2008/01/26 22:34:17 mast Exp $ +|| $Id: builtin_functions.c,v 1.651 2008/01/29 20:10:06 grubba Exp $ */ #include "global.h" @@ -3334,12 +3334,27 @@ node *fix_object_program_type(node *n) return NULL; } -/*! @decl string reverse(string s) - *! @decl array reverse(array a) - *! @decl int reverse(int i) +/*! @decl string reverse(string s, int|void start, int|void end) + *! @decl array reverse(array a, int|void start, int|void end) + *! @decl int reverse(int i, int|void start, int|void end) *! *! Reverses a string, array or int. *! + *! @param s + *! String to reverse. + *! @param a + *! Array to reverse. + *! @param i + *! Integer to reverse. + *! @param start + *! Optional start index of the range to reverse. + *! Default: @expr{0@} (zero). + *! @param end + *! Optional end index of the range to reverse. + *! Default for strings: @expr{sizeof(s)-1@}. + *! Default for arrays: @expr{sizeof(a)-1@}. + *! Default for integers: @expr{Pike.get_runtime_info()->int_size - 1@}. + *! *! This function reverses a string, char by char, an array, value *! by value or an int, bit by bit and returns the result. It's not *! destructive on the input value. @@ -3352,32 +3367,61 @@ node *fix_object_program_type(node *n) */ PMOD_EXPORT void f_reverse(INT32 args) { - if(args < 1) - SIMPLE_TOO_FEW_ARGS_ERROR("reverse", 1); + struct svalue *sv; + int start = 0, end = -1; - switch(Pike_sp[-args].type) + get_all_args("reverse", args, "%*.%d%d", &sv, &start, &end); + + switch(sv->type) { case T_STRING: { INT32 e; struct pike_string *s; - s=begin_wide_shared_string(Pike_sp[-args].u.string->len, - Pike_sp[-args].u.string->size_shift); - switch(Pike_sp[-args].u.string->size_shift) + if (start < 0) { + start = 0; + } else if (start >= sv->u.string->len) { + /* Noop. */ + pop_n_elems(args-1); + break; + } + if ((end < 0) || (end >= sv->u.string->len)) { + end = sv->u.string->len; + } else if (end <= start) { + /* Noop. */ + pop_n_elems(args-1); + break; + } else { + end++; + } + s=begin_wide_shared_string(sv->u.string->len, sv->u.string->size_shift); + switch(sv->u.string->size_shift) { case 0: - for(e=0;e<Pike_sp[-args].u.string->len;e++) - STR0(s)[e]=STR0(Pike_sp[-args].u.string)[Pike_sp[-args].u.string->len-1-e]; + for(e=0;e<start;e++) + STR0(s)[e]=STR0(sv->u.string)[e]; + for(;e<end;e++) + STR0(s)[e]=STR0(sv->u.string)[end-1-e-start]; + for(;e<sv->u.string->len;e++) + STR0(s)[e]=STR0(sv->u.string)[e]; break; case 1: - for(e=0;e<Pike_sp[-args].u.string->len;e++) - STR1(s)[e]=STR1(Pike_sp[-args].u.string)[Pike_sp[-args].u.string->len-1-e]; + for(e=0;e<start;e++) + STR1(s)[e]=STR1(sv->u.string)[e]; + for(;e<end;e++) + STR1(s)[e]=STR1(sv->u.string)[end-1-e-start]; + for(;e<sv->u.string->len;e++) + STR1(s)[e]=STR1(sv->u.string)[e]; break; case 2: - for(e=0;e<Pike_sp[-args].u.string->len;e++) - STR2(s)[e]=STR2(Pike_sp[-args].u.string)[Pike_sp[-args].u.string->len-1-e]; + for(e=0;e<start;e++) + STR2(s)[e]=STR2(sv->u.string)[e]; + for(;e<end;e++) + STR2(s)[e]=STR2(sv->u.string)[end-1-e-start]; + for(;e<sv->u.string->len;e++) + STR2(s)[e]=STR2(sv->u.string)[e]; break; } s=low_end_shared_string(s); @@ -3388,6 +3432,7 @@ PMOD_EXPORT void f_reverse(INT32 args) case T_INT: { + /* FIXME: Ought to use INT_TYPE! */ INT32 e; e=Pike_sp[-args].u.integer; e=((e & 0x55555555UL)<<1) + ((e & 0xaaaaaaaaUL)>>1); @@ -3404,8 +3449,8 @@ PMOD_EXPORT void f_reverse(INT32 args) case T_ARRAY: { - struct array *a; - a=reverse_array(Pike_sp[-args].u.array); + struct array *a = sv->u.array; + a = reverse_array(a, start, (end < 0)?a->size:end); pop_n_elems(args); push_array(a); break; @@ -9159,11 +9204,11 @@ void init_builtin_efuns(void) tFunc(tSetvar(1,tMapping) tMix tMix,tVar(1))), OPT_TRY_OPTIMIZE, optimize_replace, 0); -/* function(int:int)|function(string:string)|function(0=array:0) */ ADD_EFUN("reverse",f_reverse, - tOr3(tFunc(tInt,tInt), - tFunc(tStr,tStr), - tFunc(tSetvar(0, tArray),tVar(0))),0); + tOr3(tFunc(tInt tOr(tVoid, tInt) tOr(tVoid, tInt), tInt), + tFunc(tStr tOr(tVoid, tInt) tOr(tVoid, tInt), tStr), + tFunc(tSetvar(0, tArray) tOr(tVoid, tInt) tOr(tVoid, tInt), + tVar(0))),0); /* function(mixed,array:array) */ ADD_EFUN("rows",f_rows, -- GitLab