diff --git a/strings.scad b/strings.scad index b398e54..63a2938 100644 --- a/strings.scad +++ b/strings.scad @@ -219,35 +219,53 @@ function _str_cmp_recurse(str,sindex,pattern,plen,pindex=0,) = // Function: str_match() // Usage: -// str_match(str,pattern) +// str_match(str,pattern,[last],[all],[start]) // Description: -// Searches input string `str` for the string `pattern` and returns the index of the first or last match in `str`. -// If `pattern` is empty then it returns 0. If `pattern` doesn't match it returns undef. +// Searches input string `str` for the string `pattern` and returns the index or indices of the matches in `str`. +// By default str_match() returns the index of the first match in `str`. If `last` is true then it returns the index of the last match. +// If the pattern is the empty string the first match is at zero and the last match is the last character of the `str`. +// If `start` is set then the search begins at index start, working either forward and backward from that position. If you set `start` +// and `last` is true then the search will find the pattern if it begins at index `start`. If no match exists, returns undef. +// If you set `all` to true then all str_match() returns all of the matches in a list, or an empty list if there are no matches. // Arguments: // str = string to search // pattern = string pattern to search for // last = set to true to return the last match. Default: false +// all = set to true to return all matches as a list. Overrides last. Default: false +// start = index where the search starts // Example: // str_match("abc123def123abc","123"); // Returns 3 // str_match("abc123def123abc","b"); // Returns 1 // str_match("abc123def123abc","1234"); // Returns undef // str_match("abc",""); // Returns 0 -// str_match("abc123def123abc","123",last=true); // Returns 9 -// str_match("abc123def123abc","b",last=true); // Returns 13 -// str_match("abc123def123abc","1234",last=true); // Returns undef -// str_match("abc","",last=true); // Returns 2 -function str_match(str,pattern,last=false) = - pattern=="" ? (last?len(str)-1:0) : - last ? _str_match_last(str,pattern,len(str)-len(pattern)) : - _str_match(str,pattern,len(str)-len(pattern)); +// str_match("abc123def123", "123", start=4); // Returns 9 +// str_match("abc123def123abc","123",last=true); // Returns 9 +// str_match("abc123def123abc","b",last=true); // Returns 13 +// str_match("abc123def123abc","1234",last=true); // Returns undef +// str_match("abc","",last=true); // Returns 2 +// str_match("abc123def123", "123", start=8, last=true)); // Returns 3 +// str_match("abc123def123abc","123",all=true); // Returns [3,9] +// str_match("abc123def123abc","b",all=true); // Returns [1,13] +// str_match("abc123def123abc","1234",all=true); // Returns [] +// str_match("abc","",all=true); // Returns [0,1,2] +function str_match(str,pattern,start=undef,last=false,all=false) = + all ? _str_matches(str,pattern) : + let( start = first_defined([start,last?len(str)-len(pattern):0])) + pattern=="" ? start : + last ? _str_match_last(str,pattern,start) : + _str_match(str,pattern,len(str)-len(pattern),start); -function _str_match(str,pattern,max_sindex,sindex=0) = +function _str_match(str,pattern,max_sindex,sindex) = sindex<=max_sindex && !_str_cmp(str,sindex, pattern) ? _str_match(str,pattern,max_sindex,sindex+1) : (sindex <= max_sindex ? sindex : undef); - function _str_match_last(str,pattern,sindex) = sindex>=0 && !_str_cmp(str,sindex, pattern) ? _str_match_last(str,pattern,sindex-1) : (sindex >=0 ? sindex : undef); +function _str_matches(str,pattern) = + pattern == "" ? list_range(len(str)) : + [for(i=[0:1:len(str)-len(pattern)]) if (_str_cmp(str,i,pattern)) i]; + + // Function: str_matches() // Usage: // str_matches(str,pattern) @@ -258,13 +276,6 @@ function _str_match_last(str,pattern,sindex) = // str = string to search // pattern = string pattern to search for // Example: -// str_matches("abc123def123abc","123"); // Returns [3,9] -// str_matches("abc123def123abc","b"); // Returns [1,13] -// str_matches("abc123def123abc","1234"); // Returns [] -// str_matches("abc",""); // Returns [0,1,2] -function str_matches(str,pattern) = - pattern == "" ? list_range(len(str)) : - [for(i=[0:1:len(str)-len(pattern)]) if (_str_cmp(str,i,pattern)) i]; // Function: starts_with()