From 538a897f4264d2166da19883b15f7dba7f87cf65 Mon Sep 17 00:00:00 2001
From: Fredrik Noring <noring@nocrew.org>
Date: Fri, 21 Jan 2000 00:18:57 +0100
Subject: [PATCH] Added has_index and has_value.

Rev: src/builtin_functions.c:1.229
Rev: src/builtin_functions.h:1.11
Rev: tutorial/tutorial.wmml:1.173
---
 src/builtin_functions.c | 144 +++++++++++++++++++++++++++++++++++++++-
 src/builtin_functions.h |   4 +-
 tutorial/tutorial.wmml  |  45 ++++++++++++-
 3 files changed, 190 insertions(+), 3 deletions(-)

diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index ae0057e083..7f2f82f854 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.228 2000/01/10 00:46:26 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.229 2000/01/20 23:10:59 noring Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -463,6 +463,108 @@ void f_search(INT32 args)
   }
 }
 
+void f_has_index(INT32 args)
+{
+  int t = 0;
+  
+  if(args != 2)
+    PIKE_ERROR("has_index", "Bad number of arguments.\n", sp, args);
+
+  switch(sp[-2].type)
+  {
+    case T_STRING:
+      if(sp[-1].type == T_INT)
+	t = (0 <= sp[-1].u.integer && sp[-1].u.integer < sp[-2].u.string->len);
+  
+      pop_n_elems(args);
+      push_int(t);
+      break;
+      
+    case T_ARRAY:
+      if(sp[-1].type == T_INT)
+	t = (0 <= sp[-1].u.integer && sp[-1].u.integer < sp[-2].u.array->size);
+      
+      pop_n_elems(args);
+      push_int(t);
+      break;
+      
+    case T_MULTISET:
+    case T_MAPPING:
+      f_index(2);
+      f_zero_type(1);
+      
+      if(sp[-1].type == T_INT)
+	sp[-1].u.integer = !sp[-1].u.integer;
+      else
+	PIKE_ERROR("has_index",
+		   "Function `zero_type' gave incorrect result.\n", sp, args);
+      break;
+      
+    case T_OBJECT:
+      /* FIXME: If the object behaves like an array, it will
+	 throw an error for non-valid indices. Maybe this is
+	 the way to go (faster)?
+	 /Noring */
+
+      /* Fall-through. */
+      
+    default:
+      stack_swap();
+      f_indices(1);
+      stack_swap();
+      f_search(2);
+      
+      if(sp[-1].type == T_INT)
+	sp[-1].u.integer = (sp[-1].u.integer != -1);
+      else
+	PIKE_ERROR("has_index",
+		   "Function `search' gave incorrect result.\n", sp, args);
+  }
+}
+
+void f_has_value(INT32 args)
+{
+  if(args != 2)
+    PIKE_ERROR("has_value", "Bad number of arguments.\n", sp, args);
+
+  switch(sp[-2].type)
+  {
+    case T_MAPPING:
+      f_search(2);
+      f_zero_type(1);
+      
+      if(sp[-1].type == T_INT)
+	sp[-1].u.integer = !sp[-1].u.integer;
+      else
+	PIKE_ERROR("has_value",
+		   "Function `zero_type' gave incorrect result.\n", sp, args);
+      break;
+      
+    case T_OBJECT:
+      /* FIXME: It's very sad that we always have to do linear search
+	 with `values' in case of objects. The problem is that we cannot
+	 use `search' directly since it's undefined weather it returns
+	 -1 (array) or 0 (mapping) during e.g. some data type emulation.
+	 /Noring */
+
+      /* Fall-through. */
+      
+    case T_STRING:   /* Strings are odd. /Noring */
+    default:
+      stack_swap();
+      f_values(1);
+      stack_swap();
+
+    case T_ARRAY:
+      f_search(2);
+
+      if(sp[-1].type == T_INT)
+	sp[-1].u.integer = (sp[-1].u.integer != -1);
+      else
+	PIKE_ERROR("has_value", "Search gave incorrect result.\n", sp, args);
+  }
+}
+
 void f_backtrace(INT32 args)
 {
   INT32 frames;
@@ -5608,6 +5710,46 @@ void init_builtin_efuns(void)
 		    tFunc( tOr(tMapping,tArray) tMix tOr(tVoid,tMix), tZero)))),
 	   0);
   
+  /* Same prototype as search, except it only has two arguments. */
+  ADD_EFUN("has_index",f_has_index,
+	   tOr5(tFunc(tStr tStr tOr(tVoid,tInt),
+		      tInt),
+		tFunc(tArr(tSetvar(0,tMix)) tVar(0) tOr(tVoid,tInt),
+		      tInt),
+		tFunc(tMultiset,
+		      tInt),
+		tFunc(tMap(tSetvar(1,tMix),tSetvar(2,tMix)) tVar(2) tOr(tVoid,tVar(1)),
+		      tInt),
+
+		tIfnot(
+		  tFunc(tArr(tSetvar(0,tMix)) tVar(0) tOr(tVoid,tInt),
+			tInt),
+		  tIfnot(
+		    tFunc(tMap(tSetvar(1,tMix),tSetvar(2,tMix)) tVar(2) tOr(tVoid,tVar(1)),
+			  tInt),
+		    tFunc( tOr(tMapping,tArray) tMix tOr(tVoid,tMix), tZero)))),
+	   0);
+
+  /* Same prototype as search, except it only has two arguments. */
+  ADD_EFUN("has_value",f_has_value,
+	   tOr5(tFunc(tStr tStr tOr(tVoid,tInt),
+		      tInt),
+		tFunc(tArr(tSetvar(0,tMix)) tVar(0) tOr(tVoid,tInt),
+		      tInt),
+		tFunc(tMultiset,
+		      tInt),
+		tFunc(tMap(tSetvar(1,tMix),tSetvar(2,tMix)) tVar(2) tOr(tVoid,tVar(1)),
+		      tInt),
+
+		tIfnot(
+		  tFunc(tArr(tSetvar(0,tMix)) tVar(0) tOr(tVoid,tInt),
+			tInt),
+		  tIfnot(
+		    tFunc(tMap(tSetvar(1,tMix),tSetvar(2,tMix)) tVar(2) tOr(tVoid,tVar(1)),
+			  tInt),
+		    tFunc( tOr(tMapping,tArray) tMix tOr(tVoid,tMix), tZero)))),
+	   0);
+
 /* function(float|int,int|void:void) */
   ADD_EFUN("sleep", f_sleep,
 	   tFunc(tOr(tFlt,tInt) tOr(tInt,tVoid),tVoid),OPT_SIDE_EFFECT);
diff --git a/src/builtin_functions.h b/src/builtin_functions.h
index 54053a3263..80aa5ecab2 100644
--- a/src/builtin_functions.h
+++ b/src/builtin_functions.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: builtin_functions.h,v 1.10 1999/11/18 04:14:44 hubbe Exp $
+ * $Id: builtin_functions.h,v 1.11 2000/01/20 23:10:59 noring Exp $
  */
 #ifndef BUILTIN_EFUNS_H
 #define BUILTIN_EFUNS_H
@@ -33,6 +33,8 @@ void f_random(INT32 args);
 void f_random_seed(INT32 args);
 void f_query_num_arg(INT32 args);
 void f_search(INT32 args);
+void f_has_index(INT32 args);
+void f_has_value(INT32 args);
 void f_backtrace(INT32 args);
 void f_add_constant(INT32 args);
 void f_combine_path(INT32 args);
diff --git a/tutorial/tutorial.wmml b/tutorial/tutorial.wmml
index d68fcbe2f4..15f81765d8 100644
--- a/tutorial/tutorial.wmml
+++ b/tutorial/tutorial.wmml
@@ -13291,7 +13291,7 @@ time
 
 
 
-<function name=search title="search for a value in a string or array">
+<function name=search title="search for a value in a string, array or mapping">
 <man_syntax>
 int search(string <I>haystack</I>, string <I>needle</I>, [ int <I>start</I> ]);<br>
 int search(array <I>haystack</I>, mixed <I>needle</I>, [ int <I>start</I> ]);<br>
@@ -13315,6 +13315,49 @@ indices, values, zero_type
 </man_see>
 </function>
 
+
+
+<function name=has_index title="does the index exist?">
+<man_syntax>
+int has_index(string <I>haystack</I>, int <I>index</I>, [ int <I>start</I> ]);<br>
+int has_index(array <I>haystack</I>, int <I>index</I>, [ int <I>start</I> ]);<br>
+int has_index(mapping <I>haystack</I>, mixed <I>index</I>, [ mixed <I>start</I> ]);
+</man_syntax>
+<man_description>
+<p>Search for <i>index</i> in <i>haystack</i>. Returns 1 if the <i>index</i>
+is in the index domain of the <i>haystack</i> or 0 if not found. If the
+optional argument <i>start</i> is present search is started at this
+position.</p>
+<p>The has_index function is equivalent to
+search(indices(haystack), index, [start]) != -1.</p>
+</man_description>
+<man_see>
+indices, values, zero_type, search, has_value
+</man_see>
+</function>
+
+
+
+<function name=has_value title="does the value exist?">
+<man_syntax>
+int has_value(string <I>haystack</I>, int <I>value</I>, [ int <I>start</I> ]);<br>
+int has_value(array <I>haystack</I>, int <I>value</I>, [ int <I>start</I> ]);<br>
+int has_value(mapping <I>haystack</I>, mixed <I>value</I>, [ mixed <I>start</I> ]);
+</man_syntax>
+<man_description>
+<p>Search for <i>value</i> in <i>haystack</i>. Returns 1 if the <i>value</i>
+is in value domain of the <i>haystack</i> or 0 if not found. If the optional
+argument <i>start</i> is present search is started at this position.</p>
+<p>The has_value function is equivalent to
+search(values(haystack), value, [start]) != -1.</p>
+</man_description>
+<man_see>
+indices, values, zero_type, search, has_index
+</man_see>
+</function>
+
+
+
 <function name=sgn title="check the sign of a value">
 <man_syntax>
 int sgn(mixed <i>value</i>);<br>
-- 
GitLab