/*
* call-seq:
* sarray.longest_match(target, from_index) -> [start, length]
*
* Takes a target string and an index inside that string, and then tries
* to find the longest match from that point in the source string for this
* SuffixArray object.
*
* It returns an array of [start, length] of where in the source a length
* string from the target would match.
*
* Refer to the unit test for examples of usage.
*/
static VALUE SuffixArray_longest_match(VALUE self, VALUE target, VALUE from_index)
{
SuffixArray *sa = NULL;
Data_Get_Struct(self, SuffixArray, sa);
if(sa == NULL || sa->suffix_index == NULL || RSTRING(sa->source)->len == 0) {
rb_raise(cSAError, ERR_NOT_INITIALIZED);
}
// get the from and for_length arguments as unsigned ints
size_t from = NUM2UINT(from_index);
// get better pointers for the source (should already be in String form)
unsigned char *source_ptr = RSTRING(sa->source)->ptr;
size_t source_len = RSTRING(sa->source)->len;
// get the target as a string
VALUE target_str = StringValue(target);
// better pointers again, we also need target_len as an in/out parameter
unsigned char *target_ptr = RSTRING(target)->ptr;
size_t target_len = RSTRING(target)->len;
// check the input for validity, returning nil like in array operations
if(from > target_len) {
return Qnil;
}
// adjust for the from and for_length settings to be within the target len
target_ptr += from;
target_len -= from;
size_t start = find_longest_match(source_ptr, source_len, target_ptr, &target_len,
sa->starts, sa->ends, sa->suffix_index);
// create the 2 value return array
VALUE result = rb_ary_new();
rb_ary_push(result, INT2FIX(start));
rb_ary_push(result, INT2FIX(target_len));
return result;
}