/*
 * 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;
}