static int8_t S_derive_action(SortRule *rule, SortCache *cache) { int32_t rule_type = SortRule_Get_Type(rule); bool reverse = !!SortRule_Get_Reverse(rule); if (rule_type == SortRule_SCORE) { return COMPARE_BY_SCORE + reverse; } else if (rule_type == SortRule_DOC_ID) { return COMPARE_BY_DOC_ID + reverse; } else if (rule_type == SortRule_FIELD) { if (cache) { int8_t width = SortCache_Get_Ord_Width(cache); switch (width) { case 1: return COMPARE_BY_ORD1 + reverse; case 2: return COMPARE_BY_ORD2 + reverse; case 4: return COMPARE_BY_ORD4 + reverse; case 8: return COMPARE_BY_ORD8 + reverse; case 16: if (SortCache_Get_Native_Ords(cache)) { return COMPARE_BY_NATIVE_ORD16 + reverse; } else { return COMPARE_BY_ORD16 + reverse; } case 32: if (SortCache_Get_Native_Ords(cache)) { return COMPARE_BY_NATIVE_ORD32 + reverse; } else { return COMPARE_BY_ORD32 + reverse; } default: THROW(ERR, "Unknown width: %i8", width); } } else { return AUTO_TIE; } } else { THROW(ERR, "Unrecognized SortRule type %i32", rule_type); } UNREACHABLE_RETURN(int8_t); }
HitQueue* HitQ_init(HitQueue *self, Schema *schema, SortSpec *sort_spec, uint32_t wanted) { HitQueueIVARS *const ivars = HitQ_IVARS(self); if (sort_spec) { VArray *rules = SortSpec_Get_Rules(sort_spec); uint32_t num_rules = VA_Get_Size(rules); uint32_t action_num = 0; if (!schema) { THROW(ERR, "Can't supply sort_spec without schema"); } ivars->need_values = false; ivars->num_actions = num_rules; ivars->actions = (uint8_t*)MALLOCATE(num_rules * sizeof(uint8_t)); ivars->field_types = (FieldType**)CALLOCATE(num_rules, sizeof(FieldType*)); for (uint32_t i = 0; i < num_rules; i++) { SortRule *rule = (SortRule*)VA_Fetch(rules, i); int32_t rule_type = SortRule_Get_Type(rule); bool reverse = SortRule_Get_Reverse(rule); if (rule_type == SortRule_SCORE) { ivars->actions[action_num++] = reverse ? COMPARE_BY_SCORE_REV : COMPARE_BY_SCORE; } else if (rule_type == SortRule_DOC_ID) { ivars->actions[action_num++] = reverse ? COMPARE_BY_DOC_ID_REV : COMPARE_BY_DOC_ID; } else if (rule_type == SortRule_FIELD) { String *field = SortRule_Get_Field(rule); FieldType *type = Schema_Fetch_Type(schema, field); if (type) { ivars->field_types[action_num] = (FieldType*)INCREF(type); ivars->actions[action_num++] = reverse ? COMPARE_BY_VALUE_REV : COMPARE_BY_VALUE; ivars->need_values = true; } else { // Skip over fields we don't know how to sort on. continue; } } else { THROW(ERR, "Unknown SortRule type: %i32", rule_type); } } } else { ivars->num_actions = 2; ivars->actions = (uint8_t*)MALLOCATE(ivars->num_actions * sizeof(uint8_t)); ivars->actions[0] = COMPARE_BY_SCORE; ivars->actions[1] = COMPARE_BY_DOC_ID; } return (HitQueue*)PriQ_init((PriorityQueue*)self, wanted); }