Search self into s from a certain position.

Return null if not found.

assert 'l'.search_in("hello world", 0).from  == 2
assert 'l'.search_in("hello world", 3).from  == 3
assert 'z'.search_in("hello world", 0)       == null

If only the index of the first character if required, see search_index_in.

Note: Is used by String::search, String::search_from, and others.

Property definitions

core $ Pattern :: search_in
	# Search `self` into `s` from a certain position.
	# Return null if not found.
	#
	#     assert 'l'.search_in("hello world", 0).from  == 2
	#     assert 'l'.search_in("hello world", 3).from  == 3
	#     assert 'z'.search_in("hello world", 0)       == null
	#
	# If only the index of the first character if required, see `search_index_in`.
	#
	# Note: Is used by `String::search`, `String::search_from`, and others.
	protected fun search_in(s: Text, from: Int): nullable Match is abstract
lib/core/text/string_search.nit:33,2--43,72

core $ BM_Pattern :: search_in
	# boyer-moore search. Return null if not found
	redef fun search_in(s, from)
	do
		var to = search_index_in(s, from)
		if to < 0 then
			return null
		else
			return new Match(s.to_s, to, _length)
		end
	end
lib/core/text/string_search.nit:132,2--141,4

core $ Regex :: search_in
	# require: not optimize_has
	#
	#     assert "l".to_re.search_in("hello world", 0).from == 2
	#     assert "el+o".to_re.search_in("hello world", 0).from == 1
	#     assert "l+".to_re.search_in("hello world", 3).from == 3
	#     assert "z".to_re.search_in("hello world", 0) == null
	#     assert "cd(e)".to_re.search_in("abcdef", 2)[1].to_s == "e"
	redef fun search_in(text, charfrom)
	do
		assert not optimize_has

		var comp_res = compile
		assert comp_res == null else "Regex compilation failed with: {comp_res.message}\n".output

		var native = native
		assert native != null

		# Actually execute
		var cstr = text.to_cstring
		var rets = cstr.to_s_unsafe(text.byte_length, copy=false)
		var bytefrom = cstr.char_to_byte_index_cached(charfrom, 0, 0)
		var subcstr = cstr.fast_cstring(bytefrom)
		var eflags = gather_eflags
		var native_match = self.native_match

		var nsub = native.re_nsub
		var res = native.regexec(subcstr, nsub + 1, native_match, eflags)

		# Found one?
		if res == 0 then
			var bfrom = native_match.rm_so + bytefrom
			var bto = native_match.rm_eo - 1 + bytefrom
			var cpos = cstr.byte_to_char_index_cached(bfrom, charfrom, bytefrom)
			var len = cstr.utf8_length(bfrom, bto - bfrom + 1)
			var match = new Match(rets, cpos, len)
			var subs = match.subs

			# Add sub expressions
			for i in [1 .. nsub] do
				if native_match[i].rm_so < 0 then
					subs.add null
					continue
				end
				var sub_bfrom = native_match[i].rm_so + bytefrom
				var sub_bto = native_match[i].rm_eo - 1 + bytefrom
				var sub_cpos = cstr.byte_to_char_index_cached(sub_bfrom, cpos, bfrom)
				var sub_len = cstr.utf8_length(sub_bfrom, sub_bto - sub_bfrom + 1)
				subs.add(new Match(rets, sub_cpos, sub_len))
			end

			return match
		end

		# No more match?
		if res.is_nomatch then return null

		# Error, should be out of memory but we cover any possible error anyway
		var error_str = get_error(res)
		"Regex search failed with: {error_str}\n".output
		abort
	end
lib/core/re.nit:352,2--412,4

core :: string_search $ Char :: search_in
	redef fun search_in(s, from)
	do
		var pos = search_index_in(s, from)
		if pos < 0 then
			return null
		else
			return new Match(s.to_s, pos, 1)
		end
	end
lib/core/text/string_search.nit:317,2--325,4

core :: string_search $ Text :: search_in
	redef fun search_in(s, from)
	do
		var pos = search_index_in(s, from)
		if pos < 0 then
			return null
		else
			return new Match(s.to_s, pos, length)
		end
	end
lib/core/text/string_search.nit:346,2--354,4