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