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