Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Странная функция list_char_alike #52

Open
Mingun opened this issue Dec 22, 2019 · 1 comment
Open

Странная функция list_char_alike #52

Mingun opened this issue Dec 22, 2019 · 1 comment

Comments

@Mingun
Copy link
Contributor

Mingun commented Dec 22, 2019

Данная фунция возвращает новый список, который состоит из одинаковых элементов, потому что она извлекает из сортированного списка некоторый элемент, равный искомому, и идет по списку до тех пор, пока элемент равен искомому:

struct _list_char* list_char_alike(struct _list_char *list, const char *string)
{
if (strlen(string) < 4)
return NULL;
int id = get_add_id(list, string);
if ((id == -1) || (id == list->data_count))
return NULL;
if (strncmp(list->data[id].string, string, strlen(string)) != 0)
return NULL;
struct _list_char* list_alike = list_char_init();
for (int i = id; i < list->data_count; i++)
{
if (strncmp(list->data[i].string, string, strlen(string)) != 0)
break;
add_last(list_alike, list->data[i].string);
}
return list_alike;
}

Однако, первый элемент может быть из любого элемента подмассива одинаковых элементов, это не обязательно самый первый элемент равный искомому, из сортированного списка:
static int get_add_id(struct _list_char *list, const char *string)
{
int first = 0;
int last = list->data_count - 1;
while (first <= last)
{
int cur = (first + last) / 2;
struct _list_char_data *data = &list->data[cur];
int cmp_result = strcmp(data->string, string);
if (cmp_result == 0)
return cur;
if (cmp_result < 0)
first = cur + 1;
else
last = cur - 1;
if (first > last)
return (first + last + 1) / 2;
}
return 0;
}

Единственное место использования этой функции -- в этом месте, где, похоже, значение имеет лишь количество элементов. Но из-за указанной особенности алгоритма, вероятно, это не то количество, которое нужно -- оно может быть меньше, чем нужно:

struct _list_char* list_alike = xconfig->handle->languages[lang].pattern->alike(xconfig->handle->languages[lang].pattern, word);
if (list_alike == NULL)
{
free (word);
return;
}
/*for (int i = 0; i < list_alike->data_count; i++)
{
log_message (ERROR, "%s", list_alike->data[i].string);
}*/
if (list_alike->data_count == 1)
{
list_alike->uninit(list_alike);
list_alike = NULL;
free (word);
return;
}
p->last_pattern_id++;
if (p->last_pattern_id == list_alike->data_count)
p->last_pattern_id = 0;
log_message (DEBUG, _("Next autocompletion word '%s' from text '%s' (layout %d), rotate autocompletation..."), list_alike->data[p->last_pattern_id].string, word, get_curr_keyboard_group());
struct _buffer *tmp_buffer = buffer_init(xconfig->handle, main_window->keymap);
tmp_buffer->set_content(tmp_buffer, list_alike->data[p->last_pattern_id].string + strlen(word)*sizeof(char));
if (tmp_buffer->cur_pos == 0)
{
list_alike->uninit(list_alike);
tmp_buffer->uninit(tmp_buffer);
p->last_action = ACTION_NONE;
free (word);
return;
}
p->event->event = p->event->default_event;
p->event->send_next_event(p->event);
p->event->send_string(p->event, tmp_buffer);
p->event->send_selection(p->event, tmp_buffer->cur_pos);
p->event->default_event.xkey.keycode = 0;
tmp_buffer->uninit(tmp_buffer);
p->last_action = ACTION_AUTOCOMPLETION;
free (word);
list_alike->uninit(list_alike);
list_alike = NULL;

Из кода неочевидно, зачем вообще подсчитывать количество слов, на первый взгляд это мало на что влияет. Данное место нуждается в пристальном внимании

@Mingun
Copy link
Contributor Author

Mingun commented Dec 23, 2019

Не заметил сначала -- list_char_alike возвращает не список одинаковых элементов, а список всех элементов из _list_char, которые начинаются с искомого слова. Что тем не менее не отменяет того, что при наличии в списке дубликатов (а они там возможны, т.к. они не удаляются) не все дубликаты будут обрабатываться. Возможно, проблема как раз в том, что в списке могут быть дубликаты

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant