From 2f27ebab1089dbc110148d2ece7bffb3f74a2705 Mon Sep 17 00:00:00 2001
From: "Stephen R. van den Berg" <srb@cuci.nl>
Date: Mon, 9 Feb 2009 15:03:02 +0100
Subject: [PATCH] Implement support for array(string|array(int))*string.

Rev: src/array.c:1.222
---
 src/array.c | 131 +++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 108 insertions(+), 23 deletions(-)

diff --git a/src/array.c b/src/array.c
index 55b33d5eb0..dbead726a6 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.221 2008/07/24 15:30:56 grubba Exp $
+|| $Id: array.c,v 1.222 2009/02/09 14:03:02 srb Exp $
 */
 
 #include "global.h"
@@ -2363,43 +2363,128 @@ PMOD_EXPORT struct array *explode(struct pike_string *str,
 PMOD_EXPORT struct pike_string *implode(struct array *a,
                                         struct pike_string *del)
 {
-  INT32 len, e, inited;
+  INT32 len, e;
   PCHARP r;
-  struct pike_string *ret, *tmp;
+  struct pike_string *ret;
+  struct svalue *ae;
   int max_shift = del->size_shift;
 
   len=0;
 
-  for(e=0;e<a->size;e++)
-  {
-    if(ITEM(a)[e].type==T_STRING)
+  for(e=a->size, ae=a->item; e--; ae++)
+    switch(ae->type)
     {
-      len+=ITEM(a)[e].u.string->len + del->len;
-      if(ITEM(a)[e].u.string->size_shift > max_shift)
-	max_shift=ITEM(a)[e].u.string->size_shift;
+      case T_INT:
+	 if(!ae->u.integer)
+	   continue;		    /* skip zero (strings) */
+	 /* FALLTHROUGH */
+      default:
+	Pike_error("Arrayelement %d is not string|array(int)\n", ae-a->item);
+      case T_STRING:
+        len+=ae->u.string->len + del->len;
+        if(ae->u.string->size_shift > max_shift)
+	  max_shift=ae->u.string->size_shift;
+	break;
+      case T_ARRAY:
+	{
+	  int blen;
+	  struct svalue *ai;
+	  struct array *b = ae->u.array;
+	  blen = b->size;
+          len += blen + del->len;
+	  for(ai = b->item; blen--; ai++)
+	  {
+	    unsigned INT32 val;
+	    if (ai->type != T_INT)
+	      Pike_error("Can only convert array(int) to string, "
+		  "arrayelement %d is not an integer\n",
+		 ai-b->item);
+	    val = ai->u.integer;
+	    switch(max_shift) {
+	      case 0:
+	        if (val <= 0xff)
+	          break;
+	        max_shift = 1;
+	        /* FALL THROUGH */
+	      case 1:
+	        if (val <= 0xffff)
+	          break;
+	        max_shift = 2;
+	        /* FALL THROUGH */
+	    }
+	  }
+	}
+	break;
     }
-  }
   if(len) len-=del->len;
   
   ret=begin_wide_shared_string(len,max_shift);
   r=MKPCHARP_STR(ret);
-  inited=0;
-  for(e=0;e<a->size;e++)
-  {
-    if(ITEM(a)[e].type==T_STRING)
+  len = del->len;
+  if(e = a->size)
+    for(ae=a->item;;ae++)
     {
-      if(inited)
+      switch(ae->type)
+      {
+        case T_STRING:
+        {
+          struct pike_string *tmp = ae->u.string;
+          pike_string_cpy(r,tmp);
+          INC_PCHARP(r,tmp->len);
+          break;
+        }
+        case T_ARRAY:
+        {
+          int blen;
+          struct array *b = ae->u.array;
+          if(blen = b->size)
+          {
+            void*rp;
+            struct svalue *ai = b->item;
+            rp = r.ptr;
+            INC_PCHARP(r,blen);
+            switch(max_shift)
+            {
+              default:
+              {
+                p_wchar0 *str0 = rp;
+                do *str0++ = ai++->u.integer;
+                while(blen--);
+                break;
+              }
+              case 1:
+              {
+                p_wchar1 *str1 = rp;
+                do *str1++ = ai++->u.integer;
+                while(blen--);
+                break;
+              }
+              case 2:
+              {
+                p_wchar2 *str2 = rp;
+                do *str2++ = ai++->u.integer;
+                while(blen--);
+                break;
+              }
+            }
+          }
+          break;
+        }
+        default:
+        case T_INT:
+          if(!--e)
+	    goto ret;
+          continue;
+      }
+      if(!--e)
+        break;
+      if(len)
       {
-	pike_string_cpy(r,del);
-	INC_PCHARP(r,del->len);
+        pike_string_cpy(r,del);
+        INC_PCHARP(r,len);
       }
-      inited=1;
-      tmp=ITEM(a)[e].u.string;
-      pike_string_cpy(r,tmp);
-      INC_PCHARP(r,tmp->len);
-      len++;
     }
-  }
+ret:
   return low_end_shared_string(ret);
 }
 
-- 
GitLab