Skip to content

Commit bc3a548

Browse files
committed
com.livecode.list: Add "index of _ in _" accessor.
Add a new operation on lists: the index of <tNeedle> in <tList> which returns the 1-based index of the first element in <tList> that is equal to <tNeedle>, or 0 if no element of <tList> is equal to <tNeedle>. There are two variants of the operation: the first index of <tNeedle> in <tList> the last index of <tNeedle> in <tList> If <tNeedle> is a list, it is considered as an element of <tList> not as a subsequence of <tList>.
1 parent e98a6a8 commit bc3a548

3 files changed

Lines changed: 94 additions & 0 deletions

File tree

libscript/src/list.mlc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ public foreign handler MCListExecDeleteElementRangeOf(in Start as LCIndex, in Fi
7474
public foreign handler MCListExecDeleteFirstElementOf(inout Target as List) as undefined binds to "<builtin>"
7575
public foreign handler MCListExecDeleteLastElementOf(inout Target as List) as undefined binds to "<builtin>"
7676

77+
public foreign handler MCListEvalIndexOfElement(in IsLast as CBool, in Needle as any, in Haystack as List, out Index as LCUIndex) as undefined binds to "<builtin>"
78+
7779
--
7880

7981
/*
@@ -855,4 +857,40 @@ begin
855857
MCListRepeatForEachElement(iterator, Iterand, container)
856858
end syntax
857859

860+
----------------------------------------------------------------
861+
862+
/*
863+
Summary: Find the first or last occurrence of <Needle> within <Haystack>
864+
865+
Needle: An expression which evaluates to any value.
866+
Target: An expression which evaluates to a list.
867+
868+
Returns: Returns the index from the start of <Haystack>.
869+
870+
Example:
871+
variable tVar as List
872+
variable tOffset as Number
873+
put ["a", "b", "c", "d", "b"]
874+
put the index of "b" in tVar into tOffset
875+
-- tOffset contains 2
876+
877+
put the last index of "b" in tVar into tOffset
878+
-- tOffset contains 5
879+
880+
Description:
881+
Use `the index of` to find where particular elements occur within a
882+
list. <Haystack> is scanned for an element that is equal to <Needle>,
883+
and the position of the element found is returned. If neither the
884+
"first index" nor "last index" are specified, the index of the first
885+
element found is returned. If no element of <Haystack> is equal to
886+
<Needle>, the return value is 0.
887+
888+
Tags: Lists
889+
*/
890+
syntax ListIndex is prefix operator with precedence 1
891+
"the" ( "first" <IsLast=false> | "last" <IsLast=true> | <IsLast=false> ) "index" "of" <Needle: Expression> "in" <Haystack: Expression>
892+
begin
893+
MCListEvalIndexOfElement(IsLast, Needle, Haystack, output)
894+
end syntax
895+
858896
end module

libscript/src/module-list.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,46 @@ extern "C" MC_DLLEXPORT void MCListEvalIsNotEqualTo(MCProperListRef p_left, MCPr
441441
r_output = !MCProperListIsEqualTo(p_left, p_right);
442442
}
443443

444+
////////////////////////////////////////////////////////////////
445+
446+
static void
447+
MCListEvalIndexOfElementInRange (bool p_is_last,
448+
MCValueRef p_needle,
449+
MCProperListRef p_haystack,
450+
MCRange p_range,
451+
uindex_t & r_output)
452+
{
453+
if (MCProperListIsEmpty (p_haystack))
454+
{
455+
r_output = 0;
456+
return;
457+
}
458+
459+
uindex_t t_offset = 0;
460+
bool t_found = false;
461+
if (!p_is_last)
462+
t_found = MCProperListFirstIndexOfElementInRange (p_haystack, p_needle,
463+
p_range, t_offset);
464+
else
465+
t_found = MCProperListLastIndexOfElementInRange (p_haystack, p_needle,
466+
p_range, t_offset);
467+
468+
if (t_found)
469+
r_output = t_offset + 1;
470+
else
471+
r_output = 0;
472+
}
473+
474+
extern "C" MC_DLLEXPORT void
475+
MCListEvalIndexOfElement (bool p_is_last,
476+
MCValueRef p_needle,
477+
MCProperListRef p_haystack,
478+
uindex_t & r_output)
479+
{
480+
MCRange t_range = MCRangeMake (0, UINDEX_MAX);
481+
MCListEvalIndexOfElementInRange (p_is_last, p_needle, p_haystack, t_range, r_output);
482+
}
483+
444484
////////////////////////////////////////////////////////////////////////////////////////////////////
445485

446486
#ifdef _TEST

tests/lcb/stdlib/list.lcb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,4 +376,20 @@ public handler TestRepeatElement()
376376
test "repeat element (count)" when tCount is 4
377377
end handler
378378

379+
----------------------------------------------------------------
380+
381+
public handler TestIndex()
382+
variable t
383+
put ["x", 1, true, [], []] into t
384+
385+
test "index" when the index of 1 in t is 2
386+
test "index (list)" when the index of [] in t is 4
387+
test "index (missing)" when the index of false in t is 0
388+
389+
test "first index" when the first index of [] in t is 4
390+
test "last index" when the last index of [] in t is 5
391+
392+
test "index (empty)" when the index of 1 in [] is 0
393+
end handler
394+
379395
end module

0 commit comments

Comments
 (0)