/* ide-code-index-entries.c * * Copyright 2017-2019 Christian Hergert * Copyright 2017 Anoop Chandu * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "ide-code-index-entries" #include "config.h" #include #include "ide-code-index-entry.h" #include "ide-code-index-entries.h" G_DEFINE_INTERFACE (IdeCodeIndexEntries, ide_code_index_entries, G_TYPE_OBJECT) static void ide_code_index_entries_real_next_entries_async (IdeCodeIndexEntries *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(IdeTask) task = NULL; g_autoptr(GPtrArray) ret = NULL; IdeCodeIndexEntry *entry; g_assert (IDE_IS_MAIN_THREAD ()); g_assert (IDE_IS_CODE_INDEX_ENTRIES (self)); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); task = ide_task_new (self, cancellable, callback, user_data); ide_task_set_source_tag (task, ide_code_index_entries_real_next_entries_async); ide_task_set_priority (task, G_PRIORITY_LOW); ide_task_set_kind (task, IDE_TASK_KIND_INDEXER); ret = g_ptr_array_new_with_free_func ((GDestroyNotify)ide_code_index_entry_free); while ((entry = ide_code_index_entries_get_next_entry (self))) g_ptr_array_add (ret, g_steal_pointer (&entry)); ide_task_return_pointer (task, g_steal_pointer (&ret), g_ptr_array_unref); } static GPtrArray * ide_code_index_entries_real_next_entries_finish (IdeCodeIndexEntries *self, GAsyncResult *result, GError **error) { GPtrArray *ret; g_assert (IDE_IS_CODE_INDEX_ENTRIES (self)); g_assert (IDE_IS_TASK (result)); ret = ide_task_propagate_pointer (IDE_TASK (result), error); return IDE_PTR_ARRAY_STEAL_FULL (&ret); } static IdeCodeIndexEntry * ide_code_index_entries_real_get_next_entry (IdeCodeIndexEntries *self) { return NULL; } static void ide_code_index_entries_default_init (IdeCodeIndexEntriesInterface *iface) { iface->get_next_entry = ide_code_index_entries_real_get_next_entry; iface->next_entries_async = ide_code_index_entries_real_next_entries_async; iface->next_entries_finish = ide_code_index_entries_real_next_entries_finish; } /** * ide_code_index_entries_get_next_entry: * @self: An #IdeCodeIndexEntries instance. * * This will fetch next entry in index. * * When all of the entries have been exhausted, %NULL should be returned. * * Returns: (nullable) (transfer full): An #IdeCodeIndexEntry. * * Since: 3.32 */ IdeCodeIndexEntry * ide_code_index_entries_get_next_entry (IdeCodeIndexEntries *self) { g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL); g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRIES (self), NULL); return IDE_CODE_INDEX_ENTRIES_GET_IFACE (self)->get_next_entry (self); } /** * ide_code_index_entries_get_file: * @self: a #IdeCodeIndexEntries * * The file that was indexed. * * Returns: (transfer full): a #GFile * * Since: 3.32 */ GFile * ide_code_index_entries_get_file (IdeCodeIndexEntries *self) { g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL); g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRIES (self), NULL); return IDE_CODE_INDEX_ENTRIES_GET_IFACE (self)->get_file (self); } /** * ide_code_index_entries_next_entries_async: * @self: a #IdeCodeIndexEntries * @cancellable: (nullable): a #GCancellable or %NULL * @callback: a callback to execute upon completion * @user_data: user data for @callback, or %NULL * * Requests the next set of results from the code index asynchronously. * This allows implementations to possibly process data off the main thread * without blocking the main loop. * * Since: 3.32 */ void ide_code_index_entries_next_entries_async (IdeCodeIndexEntries *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (IDE_IS_MAIN_THREAD ()); g_return_if_fail (IDE_IS_CODE_INDEX_ENTRIES (self)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); IDE_CODE_INDEX_ENTRIES_GET_IFACE (self)->next_entries_async (self, cancellable, callback, user_data); } /** * ide_code_index_entries_next_entries_finish: * @self: a #IdeCodeIndexEntries * @result: a #GAsyncResult provided to callback * @error: a location for a #GError, or %NULL * * Completes an asynchronous request for the next set of entries from the index. * * Returns: (transfer full) (element-type IdeCodeIndexEntry): a #GPtrArray * of #IdeCodeIndexEntry. * * Since: 3.32 */ GPtrArray * ide_code_index_entries_next_entries_finish (IdeCodeIndexEntries *self, GAsyncResult *result, GError **error) { g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL); g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRIES (self), NULL); g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL); return IDE_CODE_INDEX_ENTRIES_GET_IFACE (self)->next_entries_finish (self, result, error); } static void ide_code_index_entries_collect_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeCodeIndexEntries *self = (IdeCodeIndexEntries *)object; g_autoptr(IdeTask) task = user_data; g_autoptr(GPtrArray) ret = NULL; g_autoptr(GError) error = NULL; GPtrArray *task_data; g_assert (IDE_IS_MAIN_THREAD ()); g_assert (IDE_IS_CODE_INDEX_ENTRIES (self)); g_assert (G_IS_ASYNC_RESULT (result)); g_assert (IDE_IS_TASK (task)); if (!(task_data = ide_task_get_task_data (task))) { task_data = g_ptr_array_new_with_free_func ((GDestroyNotify)ide_code_index_entry_free); ide_task_set_task_data (task, task_data, g_ptr_array_unref); } if ((ret = ide_code_index_entries_next_entries_finish (self, result, &error)) && ret->len > 0) { IDE_PTR_ARRAY_SET_FREE_FUNC (ret, NULL); for (guint i = 0; i < ret->len; i++) g_ptr_array_add (task_data, g_ptr_array_index (ret, i)); g_ptr_array_remove_range (ret, 0, ret->len); ide_code_index_entries_next_entries_async (self, ide_task_get_cancellable (task), ide_code_index_entries_collect_cb, g_object_ref (task)); return; } ide_task_return_pointer (task, g_ptr_array_ref (task_data), g_ptr_array_unref); } /** * ide_code_index_entries_collect_async: * * Calls ide_code_index_entries_next_entries_async() repeatedly until all * entries have been retrieved. After that, the async operation will complete. * * Since: 3.32 */ void ide_code_index_entries_collect_async (IdeCodeIndexEntries *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(IdeTask) task = NULL; g_return_if_fail (IDE_IS_CODE_INDEX_ENTRIES (self)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); task = ide_task_new (self, cancellable, callback, user_data); ide_task_set_source_tag (task, ide_code_index_entries_collect_async); ide_code_index_entries_next_entries_async (self, cancellable, ide_code_index_entries_collect_cb, g_steal_pointer (&task)); } /** * ide_code_index_entries_collect_finish: * * Returns: (transfer full) (element-type IdeCodeIndexEntry): an array of #IdeCodeIndexEntry * or %NULL and @error is set * * Since: 3.32 */ GPtrArray * ide_code_index_entries_collect_finish (IdeCodeIndexEntries *self, GAsyncResult *result, GError **error) { g_return_val_if_fail (IDE_IS_MAIN_THREAD (), NULL); g_return_val_if_fail (IDE_IS_CODE_INDEX_ENTRIES (self), NULL); g_return_val_if_fail (IDE_IS_TASK (result), NULL); return ide_task_propagate_pointer (IDE_TASK (result), error); }