ext/rbs_extension/location.c in rbs-3.4.4 vs ext/rbs_extension/location.c in rbs-3.5.0.pre.1

- old
+ new

@@ -1,85 +1,78 @@ #include "rbs_extension.h" +#define RBS_LOC_REQUIRED_P(loc, i) ((loc)->children->required_p & (1 << (i))) +#define RBS_LOC_OPTIONAL_P(loc, i) (!RBS_LOC_REQUIRED_P((loc), (i))) + VALUE RBS_Location; -rbs_loc_list *rbs_loc_list_add(rbs_loc_list *list, const ID name, const range r) { - rbs_loc_list *new = malloc(sizeof(rbs_loc_list)); - new->next = list; - new->name = name; - new->rg = r; - return new; +position rbs_loc_position(int char_pos) { + position pos = { 0, char_pos, -1, -1 }; + return pos; } -rbs_loc_list *rbs_loc_list_dup(rbs_loc_list *list) { - if (list) { - return rbs_loc_list_add(rbs_loc_list_dup(list->next), list->name, list->rg); - } else { - return NULL; - } +position rbs_loc_position3(int char_pos, int line, int column) { + position pos = { 0, char_pos, line, column }; + return pos; } -void rbs_loc_list_free(rbs_loc_list *list) { - while (list) { - rbs_loc_list *next = list->next; - free(list); - list = next; +static void check_children_max(unsigned short n) { + size_t max = sizeof(rbs_loc_entry_bitmap) * 8; + if (n > max) { + rb_raise(rb_eRuntimeError, "Too many children added to location: %d", n); } } -bool rbs_loc_list_find(const rbs_loc_list *list, ID name, range *rg) { - while (list) { - if (list->name == name) { - *rg = list->rg; - return true; - } +void rbs_loc_alloc_children(rbs_loc *loc, unsigned short cap) { + check_children_max(cap); - list = list->next; - } + size_t s = sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * cap; + loc->children = malloc(s); - return false; + loc->children->len = 0; + loc->children->required_p = 0; + loc->children->cap = cap; } -size_t rbs_loc_list_size(const rbs_loc_list *list) { - size_t size = 0; - - while (list) { - size += 1; - list = list->next; +static void check_children_cap(rbs_loc *loc) { + if (loc->children == NULL) { + rbs_loc_alloc_children(loc, 1); + } else { + if (loc->children->len == loc->children->cap) { + check_children_max(loc->children->cap + 1); + size_t s = sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * (++loc->children->cap); + loc->children = realloc(loc->children, s); + } } - - return size; } -position rbs_loc_position(int char_pos) { - position pos = { 0, char_pos, -1, -1 }; - return pos; -} +void rbs_loc_add_required_child(rbs_loc *loc, ID name, range r) { + check_children_cap(loc); -position rbs_loc_position3(int char_pos, int line, int column) { - position pos = { 0, char_pos, line, column }; - return pos; -} + unsigned short i = loc->children->len++; + loc->children->entries[i].name = name; + loc->children->entries[i].rg = r; -void rbs_loc_add_required_child(rbs_loc *loc, ID name, range r) { - loc->requireds = rbs_loc_list_add(loc->requireds, name, r); + loc->children->required_p |= 1 << i; } void rbs_loc_add_optional_child(rbs_loc *loc, ID name, range r) { - loc->optionals = rbs_loc_list_add(loc->optionals, name, r); + check_children_cap(loc); + + unsigned short i = loc->children->len++; + loc->children->entries[i].name = name; + loc->children->entries[i].rg = r; } void rbs_loc_init(rbs_loc *loc, VALUE buffer, range rg) { loc->buffer = buffer; loc->rg = rg; - loc->optionals = NULL; - loc->requireds = NULL; + loc->children = NULL; } void rbs_loc_free(rbs_loc *loc) { - rbs_loc_list_free(loc->optionals); - rbs_loc_list_free(loc->requireds); + free(loc->children); ruby_xfree(loc); } static void rbs_loc_mark(void *ptr) { @@ -87,11 +80,15 @@ rb_gc_mark(loc->buffer); } static size_t rbs_loc_memsize(const void *ptr) { const rbs_loc *loc = ptr; - return sizeof(*loc) + (rbs_loc_list_size(loc->optionals) + rbs_loc_list_size(loc->requireds)) * sizeof(rbs_loc_list); + if (loc->children == NULL) { + return sizeof(rbs_loc); + } else { + return sizeof(rbs_loc) + sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * loc->children->cap; + } } static rb_data_type_t location_type = { "RBS::Location", {rbs_loc_mark, (RUBY_DATA_FUNC)rbs_loc_free, rbs_loc_memsize}, @@ -128,12 +125,14 @@ rbs_loc *self_loc = rbs_check_location(self); rbs_loc *other_loc = rbs_check_location(other); self_loc->buffer = other_loc->buffer; self_loc->rg = other_loc->rg; - self_loc->requireds = rbs_loc_list_dup(other_loc->requireds); - self_loc->optionals = rbs_loc_list_dup(other_loc->optionals); + if (other_loc->children != NULL) { + rbs_loc_alloc_children(self_loc, other_loc->children->cap); + memcpy(self_loc->children, other_loc->children, sizeof(rbs_loc_children) + sizeof(rbs_loc_entry) * other_loc->children->cap); + } return Qnil; } static VALUE location_buffer(VALUE self) { @@ -219,22 +218,23 @@ } static VALUE location_aref(VALUE self, VALUE name) { rbs_loc *loc = rbs_check_location(self); - range result; ID id = SYM2ID(name); - if (rbs_loc_list_find(loc->requireds, id, &result)) { - return rbs_new_location(loc->buffer, result); - } + if (loc->children != NULL) { + for (unsigned short i = 0; i < loc->children->len; i++) { + if (loc->children->entries[i].name == id) { + range result = loc->children->entries[i].rg; - if (rbs_loc_list_find(loc->optionals, id, &result)) { - if (null_range_p(result)) { - return Qnil; - } else { - return rbs_new_location(loc->buffer, result); + if (RBS_LOC_OPTIONAL_P(loc, i) && null_range_p(result)) { + return Qnil; + } else { + return rbs_new_location(loc->buffer, result); + } + } } } VALUE string = rb_funcall(name, rb_intern("to_s"), 0); rb_raise(rb_eRuntimeError, "Unknown child name given: %s", RSTRING_PTR(string)); @@ -242,28 +242,37 @@ static VALUE location_optional_keys(VALUE self) { VALUE keys = rb_ary_new(); rbs_loc *loc = rbs_check_location(self); - rbs_loc_list *list = loc->optionals; + rbs_loc_children *children = loc->children; + if (children == NULL) { + return keys; + } - while (list) { - rb_ary_push(keys, ID2SYM(list->name)); - list = list->next; + for (unsigned short i = 0; i < children->len; i++) { + if (RBS_LOC_OPTIONAL_P(loc, i)) { + rb_ary_push(keys, ID2SYM(children->entries[i].name)); + + } } return keys; } static VALUE location_required_keys(VALUE self) { VALUE keys = rb_ary_new(); rbs_loc *loc = rbs_check_location(self); - rbs_loc_list *list = loc->requireds; + rbs_loc_children *children = loc->children; + if (children == NULL) { + return keys; + } - while (list) { - rb_ary_push(keys, ID2SYM(list->name)); - list = list->next; + for (unsigned short i = 0; i < children->len; i++) { + if (RBS_LOC_REQUIRED_P(loc, i)) { + rb_ary_push(keys, ID2SYM(children->entries[i].name)); + } } return keys; }