summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--doc/lsearch.n67
-rw-r--r--generic/tclCmdIL.c394
-rw-r--r--tests/lsearch.test100
4 files changed, 399 insertions, 169 deletions
diff --git a/ChangeLog b/ChangeLog
index 13f300d..7dbb452 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2002-03-06 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * doc/lsearch.n: Documentation of new features, plus examples.
+ * tests/lsearch.test: Tests of new features.
+ * generic/tclCmdIL.c (Tcl_LsearchObjCmd): TIP#80 support. See
+ http://purl.org/tcl/tip/80 for details.
+
2002-03-05 Jeff Hobbs <jeffh@ActiveState.com>
*** 8.4a4 TAGGED FOR RELEASE ***
diff --git a/doc/lsearch.n b/doc/lsearch.n
index 48c24b8..30ce348 100644
--- a/doc/lsearch.n
+++ b/doc/lsearch.n
@@ -6,7 +6,7 @@
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
-'\" RCS: @(#) $Id: lsearch.n,v 1.9 2001/11/14 23:38:39 hobbs Exp $
+'\" RCS: @(#) $Id: lsearch.n,v 1.10 2002/03/06 11:28:08 dkf Exp $
'\"
.so man.macros
.TH lsearch n 8.4 Tcl "Tcl Built-In Commands"
@@ -22,10 +22,19 @@ lsearch \- See if a list contains a particular element
.PP
This command searches the elements of \fIlist\fR to see if one
of them matches \fIpattern\fR. If so, the command returns the index
-of the first matching element. If not, the command returns \fB\-1\fR.
-The \fIoption\fR arguments indicates how the elements of the list are to
-be matched against \fIpattern\fR and it must have one of the following
-values:
+of the first matching element
+.VS 8.4
+(unless the options \fB\-all\fR or \fB\-inline\fR are specified.)
+.VE 8.4
+If not, the command returns \fB\-1\fR. The \fIoption\fR arguments
+indicates how the elements of the list are to be matched against
+\fIpattern\fR and it must have one of the following values:
+.TP
+\fB\-all\fR
+.VS 8.4
+Changes the result to be the list of all matching indices (or all
+matching values if \fB\-inline\fR is specified as well.)
+.VE 8.4
.TP
\fB\-ascii\fR
The list elements are to be examined as ASCII strings. This option is only
@@ -43,17 +52,30 @@ comparisons. This option is only meaningful when used with
\fB\-exact\fR
The list element must contain exactly the same string as \fIpattern\fR.
.TP
+\fB\-glob\fR
+\fIPattern\fR is a glob-style pattern which is matched against each list
+element using the same rules as the \fBstring match\fR command.
+.TP
\fB\-increasing\fR
The list elements are sorted in increasing order. This option is only
meaningful when used with \fB\-sorted\fR.
.TP
+\fB\-inline\fR
+.VS 8.4
+The matching value is returned instead of its index (or an empty
+string if no value matches.) If \fB\-all\fR is also specified, then
+the result of the command is the list of all values that matched.
+.VE 8.4
+.TP
\fB\-integer\fR
The list elements are to be compared as integers. This option is only
meaningful when used with \fB\-exact\fR or \fB\-sorted\fR.
.TP
-\fB\-glob\fR
-\fIPattern\fR is a glob-style pattern which is matched against each list
-element using the same rules as the \fBstring match\fR command.
+\fB\-not\fR
+.VS 8.4
+This negates the sense of the match, returning the index of the first
+non-matching value in the list.
+.VE 8.4
.TP
\fB\-real\fR
The list elements are to be compared as floating-point values. This
@@ -69,7 +91,16 @@ The list elements are in sorted order. If this option is specified,
\fBlsearch\fR will use a more efficient searching algorithm to search
\fIlist\fR. If no other options are specified, \fIlist\fR is assumed
to be sorted in increasing order, and to contain ASCII strings. This
-option cannot be used with \fB\-glob\fR or \fB\-regexp\fR.
+option cannot be used with \fB\-all\fR, \fB\-glob\fR, \fB\-not\fR or
+\fB\-regexp\fR.
+.TP
+\fB\-start\fR \fIindex\fR
+.VS 8.4
+The list is searched starting at position \fIindex\fR. If \fIindex\fR
+has the value \fBend\fR, it refers to the last element in the list,
+and \fBend\-\fIinteger\fR refers to the last element in the list minus
+the specified integer offset.
+.VE 8.4
.PP
If \fIoption\fR is omitted then it defaults to \fB\-glob\fR. If more
than one of \fB\-exact\fR, \fB\-glob\fR, \fB\-regexp\fR, and
@@ -77,11 +108,25 @@ than one of \fB\-exact\fR, \fB\-glob\fR, \fB\-regexp\fR, and
precendence. If more than one of \fB\-ascii\fR, \fB\-dictionary\fR,
\fB\-integer\fR and \fB\-real\fR is specified, the option specified
last takes precendence. If more than one of \fB\-increasing\fR and
-\fB\-decreasing\fR is specified, the option specified last takes precedence.
+\fB\-decreasing\fR is specified, the option specified last takes
+precedence.
+
+.SH EXAMPLES
+.VS 8.4
+.CS
+lsearch {a b c d e} c => 2
+lsearch -all {a b c a b c} c => 2 5
+lsearch -data {a20 b35 c47} b* => b35
+lsearch -data -not {a20 b35 c47} b* => a20
+lsearch -all -data -not {a20 b35 c47} b* => a20 c47
+lsearch -all -not {a20 b35 c47} b* => 0 2
+lsearch -start 3 {a b c a b c} c => 5
+.CE
+.VE 8.4
.SH "SEE ALSO"
.VS 8.4
-list(n), lappend(n), lindex(n), linsert(n), llength(n),
+foreach(n), list(n), lappend(n), lindex(n), linsert(n), llength(n),
lset(n), lsort(n), lrange(n), lreplace(n)
.VE
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index f7cdf29..405245a 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -15,7 +15,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdIL.c,v 1.41 2002/02/15 14:28:48 dkf Exp $
+ * RCS: @(#) $Id: tclCmdIL.c,v 1.42 2002/03/06 11:28:08 dkf Exp $
*/
#include "tclInt.h"
@@ -2767,22 +2767,24 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
char *bytes, *patternBytes;
int i, match, mode, index, result, listc, length, elemLen;
int dataType, isIncreasing, lower, upper, patInt, objInt;
+ int offset, allMatches, inlineReturn, negatedMatch;
double patDouble, objDouble;
- Tcl_Obj *patObj, **listv;
+ Tcl_Obj *patObj, **listv, *listPtr, *startPtr;
static CONST char *options[] = {
- "-ascii", "-decreasing", "-dictionary", "-exact", "-increasing",
- "-integer", "-glob", "-real", "-regexp", "-sorted", NULL
+ "-all", "-ascii", "-decreasing", "-dictionary",
+ "-exact", "-glob", "-increasing", "-inline",
+ "-integer", "-not", "-real", "-regexp",
+ "-sorted", "-start", NULL
};
enum options {
- LSEARCH_ASCII, LSEARCH_DECREASING, LSEARCH_DICTIONARY, LSEARCH_EXACT,
- LSEARCH_INCREASING, LSEARCH_INTEGER, LSEARCH_GLOB,
- LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED
+ LSEARCH_ALL, LSEARCH_ASCII, LSEARCH_DECREASING, LSEARCH_DICTIONARY,
+ LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING, LSEARCH_INLINE,
+ LSEARCH_INTEGER, LSEARCH_NOT, LSEARCH_REAL, LSEARCH_REGEXP,
+ LSEARCH_SORTED, LSEARCH_START
};
-
enum datatypes {
ASCII, DICTIONARY, INTEGER, REAL
};
-
enum modes {
EXACT, GLOB, REGEXP, SORTED
};
@@ -2790,48 +2792,93 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
mode = GLOB;
dataType = ASCII;
isIncreasing = 1;
-
+ allMatches = 0;
+ inlineReturn = 0;
+ negatedMatch = 0;
+ listPtr = NULL;
+ startPtr = NULL;
+ offset = 0;
+
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "?options? list pattern");
return TCL_ERROR;
}
-
+
for (i = 1; i < objc-2; i++) {
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index)
!= TCL_OK) {
+ if (startPtr) {
+ Tcl_DecrRefCount(startPtr);
+ }
return TCL_ERROR;
}
switch ((enum options) index) {
- case LSEARCH_ASCII: /* -ascii */
- dataType = ASCII;
- break;
- case LSEARCH_DECREASING: /* -decreasing */
- isIncreasing = 0;
- break;
- case LSEARCH_DICTIONARY: /* -dictionary */
- dataType = DICTIONARY;
- break;
- case LSEARCH_EXACT: /* -increasing */
- mode = EXACT;
- break;
- case LSEARCH_INCREASING: /* -increasing */
- isIncreasing = 1;
- break;
- case LSEARCH_INTEGER: /* -integer */
- dataType = INTEGER;
- break;
- case LSEARCH_GLOB: /* -glob */
- mode = GLOB;
- break;
- case LSEARCH_REAL: /* -real */
- dataType = REAL;
- break;
- case LSEARCH_REGEXP: /* -regexp */
- mode = REGEXP;
- break;
- case LSEARCH_SORTED: /* -sorted */
- mode = SORTED;
- break;
+ case LSEARCH_ALL: /* -all */
+ allMatches = 1;
+ break;
+ case LSEARCH_ASCII: /* -ascii */
+ dataType = ASCII;
+ break;
+ case LSEARCH_DECREASING: /* -decreasing */
+ isIncreasing = 0;
+ break;
+ case LSEARCH_DICTIONARY: /* -dictionary */
+ dataType = DICTIONARY;
+ break;
+ case LSEARCH_EXACT: /* -increasing */
+ mode = EXACT;
+ break;
+ case LSEARCH_GLOB: /* -glob */
+ mode = GLOB;
+ break;
+ case LSEARCH_INCREASING: /* -increasing */
+ isIncreasing = 1;
+ break;
+ case LSEARCH_INLINE: /* -inline */
+ inlineReturn = 1;
+ break;
+ case LSEARCH_INTEGER: /* -integer */
+ dataType = INTEGER;
+ break;
+ case LSEARCH_NOT: /* -not */
+ negatedMatch = 1;
+ break;
+ case LSEARCH_REAL: /* -real */
+ dataType = REAL;
+ break;
+ case LSEARCH_REGEXP: /* -regexp */
+ mode = REGEXP;
+ break;
+ case LSEARCH_SORTED: /* -sorted */
+ mode = SORTED;
+ break;
+ case LSEARCH_START: /* -start */
+ /*
+ * If there was a previous -start option, release its saved
+ * index because it will either be replaced or there will be
+ * an error.
+ */
+ if (startPtr) {
+ Tcl_DecrRefCount(startPtr);
+ }
+ if (i > objc-4) {
+ Tcl_AppendResult(interp, "missing starting index", NULL);
+ return TCL_ERROR;
+ }
+ i++;
+ if (objv[i] == objv[objc - 2]) {
+ /*
+ * Take copy to prevent shimmering problems. Note
+ * that it does not matter if the index obj is also a
+ * component of the list being searched. We only need
+ * to copy where the list and the index are
+ * one-and-the-same.
+ */
+ startPtr = Tcl_DuplicateObj(objv[i]);
+ } else {
+ startPtr = objv[i];
+ Tcl_IncrRefCount(startPtr);
+ }
}
}
@@ -2842,29 +2889,48 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
result = Tcl_ListObjGetElements(interp, objv[objc - 2], &listc, &listv);
if (result != TCL_OK) {
+ if (startPtr) {
+ Tcl_DecrRefCount(startPtr);
+ }
return result;
}
+ /*
+ * Get the user-specified start offset.
+ */
+ if (startPtr) {
+ result = TclGetIntForIndex(interp, startPtr, listc-1, &offset);
+ Tcl_DecrRefCount(startPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (offset < 0) {
+ offset = 0;
+ } else if (offset > listc-1) {
+ offset = listc-1;
+ }
+ }
+
patObj = objv[objc - 1];
patternBytes = NULL;
if ((enum modes) mode == EXACT || (enum modes) mode == SORTED) {
switch ((enum datatypes) dataType) {
- case ASCII:
- case DICTIONARY:
- patternBytes = Tcl_GetStringFromObj(patObj, &length);
- break;
- case INTEGER:
- result = Tcl_GetIntFromObj(interp, patObj, &patInt);
- if (result != TCL_OK) {
- return result;
- }
- break;
- case REAL:
- result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble);
- if (result != TCL_OK) {
- return result;
- }
- break;
+ case ASCII:
+ case DICTIONARY:
+ patternBytes = Tcl_GetStringFromObj(patObj, &length);
+ break;
+ case INTEGER:
+ result = Tcl_GetIntFromObj(interp, patObj, &patInt);
+ if (result != TCL_OK) {
+ return result;
+ }
+ break;
+ case REAL:
+ result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble);
+ if (result != TCL_OK) {
+ return result;
+ }
+ break;
}
} else {
patternBytes = Tcl_GetStringFromObj(patObj, &length);
@@ -2877,52 +2943,54 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
*/
index = -1;
match = 0;
- if ((enum modes) mode == SORTED) {
- /* If the data is sorted, we can do a more intelligent search */
- lower = -1;
+
+ if ((enum modes) mode == SORTED && !allMatches && !negatedMatch) {
+ /*
+ * If the data is sorted, we can do a more intelligent search.
+ * Note that there is no point in being smart when -all was
+ * specified; in that case, we have to look at all items anyway,
+ * and there is no sense in doing this when the match sense is
+ * inverted.
+ */
+ lower = offset - 1;
upper = listc;
while (lower + 1 != upper) {
i = (lower + upper)/2;
switch ((enum datatypes) dataType) {
- case ASCII: {
- bytes = Tcl_GetString(listv[i]);
- match = strcmp(patternBytes, bytes);
- break;
+ case ASCII:
+ bytes = Tcl_GetString(listv[i]);
+ match = strcmp(patternBytes, bytes);
+ break;
+ case DICTIONARY:
+ bytes = Tcl_GetString(listv[i]);
+ match = DictionaryCompare(patternBytes, bytes);
+ break;
+ case INTEGER:
+ result = Tcl_GetIntFromObj(interp, listv[i], &objInt);
+ if (result != TCL_OK) {
+ return result;
}
- case DICTIONARY: {
- bytes = Tcl_GetString(listv[i]);
- match = DictionaryCompare(patternBytes, bytes);
- break;
+ if (patInt == objInt) {
+ match = 0;
+ } else if (patInt < objInt) {
+ match = -1;
+ } else {
+ match = 1;
}
- case INTEGER: {
- result = Tcl_GetIntFromObj(interp, listv[i], &objInt);
- if (result != TCL_OK) {
- return result;
- }
- if (patInt == objInt) {
- match = 0;
- } else if (patInt < objInt) {
- match = -1;
- } else {
- match = 1;
- }
- break;
+ break;
+ case REAL:
+ result = Tcl_GetDoubleFromObj(interp, listv[i], &objDouble);
+ if (result != TCL_OK) {
+ return result;
}
- case REAL: {
- result = Tcl_GetDoubleFromObj(interp, listv[i],
- &objDouble);
- if (result != TCL_OK) {
- return result;
- }
- if (patDouble == objDouble) {
- match = 0;
- } else if (patDouble < objDouble) {
- match = -1;
- } else {
- match = 1;
- }
- break;
+ if (patDouble == objDouble) {
+ match = 0;
+ } else if (patDouble < objDouble) {
+ match = -1;
+ } else {
+ match = 1;
}
+ break;
}
if (match == 0) {
/*
@@ -2953,68 +3021,110 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv)
}
}
}
+
} else {
- for (i = 0; i < listc; i++) {
+ /*
+ * We need to do a linear search, because (at least one) of:
+ * - our matcher can only tell equal vs. not equal
+ * - our matching sense is negated
+ * - we're building a list of all matched items
+ */
+ if (allMatches) {
+ listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ }
+ for (i = offset; i < listc; i++) {
match = 0;
switch ((enum modes) mode) {
- case SORTED:
- case EXACT: {
- switch ((enum datatypes) dataType) {
- case ASCII: {
- bytes = Tcl_GetStringFromObj(listv[i], &elemLen);
- if (length == elemLen) {
- match = (memcmp(bytes, patternBytes,
- (size_t) length) == 0);
- }
- break;
- }
- case DICTIONARY: {
- bytes = Tcl_GetString(listv[i]);
- match =
- (DictionaryCompare(bytes, patternBytes) == 0);
- break;
- }
- case INTEGER: {
- result = Tcl_GetIntFromObj(interp, listv[i],
- &objInt);
- if (result != TCL_OK) {
- return result;
- }
- match = (objInt == patInt);
- break;
- }
- case REAL: {
- result = Tcl_GetDoubleFromObj(interp, listv[i],
- &objDouble);
- if (result != TCL_OK) {
- return result;
- }
- match = (objDouble == patDouble);
- break;
+ case SORTED:
+ case EXACT:
+ switch ((enum datatypes) dataType) {
+ case ASCII:
+ bytes = Tcl_GetStringFromObj(listv[i], &elemLen);
+ if (length == elemLen) {
+ match = (memcmp(bytes, patternBytes,
+ (size_t) length) == 0);
+ }
+ break;
+ case DICTIONARY:
+ bytes = Tcl_GetString(listv[i]);
+ match = (DictionaryCompare(bytes, patternBytes) == 0);
+ break;
+ case INTEGER:
+ result = Tcl_GetIntFromObj(interp, listv[i], &objInt);
+ if (result != TCL_OK) {
+ if (listPtr) {
+ Tcl_DecrRefCount(listPtr);
}
+ return result;
}
+ match = (objInt == patInt);
break;
- }
- case GLOB: {
- match = Tcl_StringMatch(Tcl_GetString(listv[i]),
- patternBytes);
+ case REAL:
+ result = Tcl_GetDoubleFromObj(interp, listv[i],
+ &objDouble);
+ if (result != TCL_OK) {
+ if (listPtr) {
+ Tcl_DecrRefCount(listPtr);
+ }
+ return result;
+ }
+ match = (objDouble == patDouble);
break;
}
- case REGEXP: {
- match = Tcl_RegExpMatchObj(interp, listv[i], patObj);
- if (match < 0) {
- return TCL_ERROR;
+ break;
+ case GLOB:
+ match = Tcl_StringMatch(Tcl_GetString(listv[i]),
+ patternBytes);
+ break;
+ case REGEXP:
+ match = Tcl_RegExpMatchObj(interp, listv[i], patObj);
+ if (match < 0) {
+ if (listPtr) {
+ Tcl_DecrRefCount(listPtr);
}
- break;
+ return TCL_ERROR;
}
+ break;
+ }
+ /*
+ * Invert match condition for -not
+ */
+ if (negatedMatch) {
+ match = !match;
}
if (match != 0) {
- index = i;
- break;
+ if (!allMatches) {
+ index = i;
+ break;
+ } else if (inlineReturn) {
+ /*
+ * Note that these appends are not expected to fail.
+ */
+ Tcl_ListObjAppendElement(interp, listPtr, listv[i]);
+ } else {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewIntObj(i));
+ }
}
}
}
- Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
+
+ /*
+ * Return everything or a single value.
+ */
+ if (allMatches) {
+ Tcl_SetObjResult(interp, listPtr);
+ } else if (!inlineReturn) {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), index);
+ } else if (index < 0) {
+ /*
+ * Is this superfluous? The result should be a blank object
+ * by default...
+ */
+ Tcl_SetObjResult(interp, Tcl_NewObj());
+ } else {
+ Tcl_SetObjResult(interp, listv[index]);
+ }
return TCL_OK;
}
diff --git a/tests/lsearch.test b/tests/lsearch.test
index 44ec96e..887edb9 100644
--- a/tests/lsearch.test
+++ b/tests/lsearch.test
@@ -11,7 +11,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: lsearch.test,v 1.7 2001/09/12 20:28:50 dgp Exp $
+# RCS: @(#) $Id: lsearch.test,v 1.8 2002/03/06 11:28:08 dkf Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
@@ -61,7 +61,7 @@ test lsearch-2.9 {search modes} {
} 1
test lsearch-2.10 {search modes} {
list [catch {lsearch -glib {b.x bx xy bcx} b.x} msg] $msg
-} {1 {bad option "-glib": must be -ascii, -decreasing, -dictionary, -exact, -increasing, -integer, -glob, -real, -regexp, or -sorted}}
+} {1 {bad option "-glib": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}}
test lsearch-3.1 {lsearch errors} {
list [catch lsearch msg] $msg
@@ -71,10 +71,10 @@ test lsearch-3.2 {lsearch errors} {
} {1 {wrong # args: should be "lsearch ?options? list pattern"}}
test lsearch-3.3 {lsearch errors} {
list [catch {lsearch a b c} msg] $msg
-} {1 {bad option "a": must be -ascii, -decreasing, -dictionary, -exact, -increasing, -integer, -glob, -real, -regexp, or -sorted}}
+} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}}
test lsearch-3.4 {lsearch errors} {
list [catch {lsearch a b c d} msg] $msg
-} {1 {bad option "a": must be -ascii, -decreasing, -dictionary, -exact, -increasing, -integer, -glob, -real, -regexp, or -sorted}}
+} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}}
test lsearch-3.5 {lsearch errors} {
list [catch {lsearch "\{" b} msg] $msg
} {1 {unmatched open brace in list}}
@@ -267,21 +267,89 @@ test lsearch-9.4 {decreasing sorted ascii search} {
set res
} [list 6 5 4 3 2 1 0]
+test lsearch-10.1 {offset searching} {
+ lsearch -start 2 {a b c a b c} a
+} 3
+test lsearch-10.2 {offset searching} {
+ lsearch -start 2 {a b c d e f} a
+} -1
+test lsearch-10.3 {offset searching} {
+ lsearch -start end-4 {a b c a b c} a
+} 3
+test lsearch-10.4 {offset searching} {
+ list [catch {lsearch -start foobar {a b c a b c} a} msg] $msg
+} {1 {bad index "foobar": must be integer or end?-integer?}}
+test lsearch-10.5 {offset searching} {
+ list [catch {lsearch -start 1 2} msg] $msg
+} {1 {missing starting index}}
+test lsearch-10.6 {binary search with offset} {
+ set res {}
+ for {set i 0} {$i < 100} {incr i} {
+ lappend res [lsearch -integer -start 2 -sorted $increasingIntegers $i]
+ }
+ set res
+} [concat -1 -1 [lrange $increasingIntegers 2 end]]
+test lsearch-11.1 {negated searches} {
+ lsearch -not {a a a b a a a} a
+} 3
+test lsearch-11.2 {negated searches} {
+ lsearch -not {a a a a a a a} a
+} -1
-# cleanup
-catch {unset res}
-::tcltest::cleanupTests
-return
-
-
-
-
-
-
-
-
+test lsearch-12.1 {return values instead of indices} {
+ lsearch -glob -inline {a1 b2 c3 d4} c*
+} c3
+test lsearch-12.2 {return values instead of indices} {
+ lsearch -glob -inline {a1 b2 c3 d4} e*
+} {}
+test lsearch-13.1 {search for all matches} {
+ lsearch -all {a b a c a d} 1
+} {}
+test lsearch-13.2 {search for all matches} {
+ lsearch -all {a b a c a d} a
+} {0 2 4}
+test lsearch-13.1 {combinations: -all and -inline} {
+ lsearch -all -inline -glob {a1 b2 a3 c4 a5 d6} a*
+} {a1 a3 a5}
+test lsearch-13.2 {combinations: -all, -inline and -not} {
+ lsearch -all -inline -not -glob {a1 b2 a3 c4 a5 d6} a*
+} {b2 c4 d6}
+test lsearch-13.3 {combinations: -all and -not} {
+ lsearch -all -not -glob {a1 b2 a3 c4 a5 d6} a*
+} {1 3 5}
+test lsearch-13.4 {combinations: -inline and -not} {
+ lsearch -inline -not -glob {a1 b2 a3 c4 a5 d6} a*
+} {b2}
+test lsearch-13.5 {combinations: -start, -all and -inline} {
+ lsearch -start 2 -all -inline -glob {a1 b2 a3 c4 a5 d6} a*
+} {a3 a5}
+test lsearch-13.6 {combinations: -start, -all, -inline and -not} {
+ lsearch -start 2 -all -inline -not -glob {a1 b2 a3 c4 a5 d6} a*
+} {c4 d6}
+test lsearch-13.7 {combinations: -start, -all and -not} {
+ lsearch -start 2 -all -not -glob {a1 b2 a3 c4 a5 d6} a*
+} {3 5}
+test lsearch-13.8 {combinations: -start, -inline and -not} {
+ lsearch -start 2 -inline -not -glob {a1 b2 a3 c4 a5 d6} a*
+} {c4}
+test lsearch-14.1 {make sure no shimmering occurs} {
+ set x [expr int(sin(0))]
+ lsearch -start $x $x $x
+} 0
+# cleanup
+catch {unset res}
+catch {unset increasingIntegers}
+catch {unset decreasingIntegers}
+catch {unset increasingDoubles}
+catch {unset decreasingDoubles}
+catch {unset increasingStrings}
+catch {unset decreasingStrings}
+catch {unset increasingDictionary}
+catch {unset decreasingDictionary}
+::tcltest::cleanupTests
+return