diff --git a/src/builtin_functions.c b/src/builtin_functions.c index ae0057e083dd74e942614c28e225bb4d82783176..7f2f82f8546387c1ff6acf6c7e5d3294ca09d20f 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 54053a326345415c74a24c0bc76f7ceb8caf2a27..80aa5ecab2843178df60a4dc3a12e899da2b55ea 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 d68fcbe2f43fb679089f10237909e18d223d8a16..15f81765d80c9aeeba4288b1a4677d873a36517b 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>