13#include <glib-object.h>
19#define TAG_NEW(T) ((T) = g_slice_new0(TMTag))
20#define TAG_FREE(T) g_slice_free(TMTag, (T))
25static GHashTable *alive_tags =
NULL;
27static void foreach_tags_log(gpointer key, gpointer value, gpointer data)
29 gsize *ref_count = data;
30 const TMTag *tag = value;
33 g_debug(
"Leaked TMTag (%d refs): %s", tag->
refcount, tag->
name);
36static void log_refs_at_exit(
void)
40 g_hash_table_foreach(alive_tags, foreach_tags_log, &ref_count);
41 g_debug(
"TMTag references left at exit: %lu", ref_count);
44static TMTag *log_tag_new(
void)
50 alive_tags = g_hash_table_new(g_direct_hash, g_direct_equal);
51 atexit(log_refs_at_exit);
54 g_hash_table_insert(alive_tags, tag, tag);
59static void log_tag_free(
TMTag *tag)
61 g_return_if_fail(alive_tags !=
NULL);
63 if (! g_hash_table_remove(alive_tags, tag)) {
64 g_critical(
"Freeing invalid TMTag pointer %p", (
void *) tag);
72#define TAG_NEW(T) ((T) = log_tag_new())
73#define TAG_FREE(T) log_tag_free(T)
93 static GType gtype = 0;
94 if (G_UNLIKELY (gtype == 0))
96 gtype = g_boxed_type_register_static(
"TMTag", (GBoxedCopyFunc)
tm_tag_ref,
140 if (
NULL != tag && g_atomic_int_dec_and_test(&tag->
refcount))
161static gint
tm_tag_compare(gconstpointer ptr1, gconstpointer ptr2, gpointer user_data)
163 unsigned int *sort_attr;
171 g_warning(
"Found NULL tag");
208 int line_diff = (t1->
line - t2->
line);
210 returnval = line_diff ? line_diff : returnval;
250 g_return_if_fail(tags_array);
252 for (i=0,
count = 0; i < tags_array->len; ++i)
254 if (
NULL != tags_array->pdata[i])
255 tags_array->pdata[
count++] = tags_array->pdata[i];
257 tags_array->len =
count;
272 g_return_if_fail(tags_array);
273 if (tags_array->len < 2)
278 for (i = 1; i < tags_array->len; ++i)
280 if (0 ==
tm_tag_compare(&(tags_array->pdata[i - 1]), &(tags_array->pdata[i]), &sort_options))
282 if (unref_duplicates)
284 tags_array->pdata[i-1] =
NULL;
298 gboolean dedup, gboolean unref_duplicates)
302 g_return_if_fail(tags_array);
306 g_ptr_array_sort_with_data(tags_array,
tm_tag_compare, &sort_options);
308 tm_tags_dedup(tags_array, sort_attributes, unref_duplicates);
327 tags_array->len / source_file->
tags_array->len < 20)
329 for (i = 0; i < tags_array->len; i++)
331 TMTag *tag = tags_array->pdata[i];
333 if (tag->
file == source_file)
334 tags_array->pdata[i] =
NULL;
339 GPtrArray *to_delete = g_ptr_array_sized_new(source_file->
tags_array->len);
341 for (i = 0; i < source_file->
tags_array->len; i++)
350 for (j = 0; j < tag_count; j++)
352 if (*found !=
NULL && (*found)->file == source_file)
355 g_ptr_array_add(to_delete, found);
364 for (i = 0; i < to_delete->len; i++)
366 TMTag **tag = to_delete->pdata[i];
369 g_ptr_array_free(to_delete, TRUE);
380static GPtrArray *
merge(GPtrArray *big_array, GPtrArray *small_array,
386 GPtrArray *res_array = g_ptr_array_sized_new(big_array->len + small_array->len);
392 if (small_array->len > big_array->len)
394 GPtrArray *tmp = small_array;
395 small_array = big_array;
402 initial_step = (small_array->len > 0) ? big_array->len / small_array->len : 1;
403 initial_step = initial_step > 4 ? initial_step : 1;
406 while (i1 < big_array->len && i2 < small_array->len)
409 gpointer val2 = small_array->pdata[i2];
413 guint j1 = (i1 + step < big_array->len) ? i1 + step : big_array->len - 1;
415 val1 = big_array->pdata[j1];
426 val1 = big_array->pdata[i1];
427 g_ptr_array_add(res_array, val1);
444 val1 = big_array->pdata[i1];
448 g_ptr_array_add(res_array, val1);
453 g_ptr_array_add(res_array, val2);
460 if (unref_duplicates)
468 while (i1 < big_array->len)
469 g_ptr_array_add(res_array, big_array->pdata[i1++]);
470 while (i2 < small_array->len)
471 g_ptr_array_add(res_array, small_array->pdata[i2++]);
474 printf(
"cmpnums: %u\n", cmpnum);
475 printf(
"total tags: %u\n", big_array->len);
476 printf(
"merged tags: %u\n\n", small_array->len);
485 GPtrArray *res_array;
490 res_array =
merge(big_array, small_array, &sort_options, unref_duplicates);
510 g_return_val_if_fail(tags_array,
NULL);
512 new_tags = g_ptr_array_new();
513 for (i=0; i < tags_array->len; ++i)
515 if (
NULL != tags_array->pdata[i])
517 if (tag_types & (((
TMTag *) tags_array->pdata[i])->type))
518 g_ptr_array_add(new_tags, tags_array->pdata[i]);
534 for (i = 0; i < tags_array->len; ++i)
537 g_ptr_array_free(tags_array, TRUE);
539 g_ptr_array_set_size(tags_array, 0);
546 GCompareDataFunc compar, gpointer user_data)
557 p = (gpointer) (((
const gchar *) base) + (idx *
sizeof(gpointer)));
558 comparison = (*compar) (key, p, user_data);
561 else if (comparison > 0)
570static gint
tag_search_cmp(gconstpointer ptr1, gconstpointer ptr2, gpointer user_data)
577 const GPtrArray *tags_array = sort_options->
tags_array;
582 if (sort_options->
first && ptr2 != &tags_array->pdata[0]) {
586 else if (!sort_options->
first && ptr2 != &tags_array->pdata[tags_array->len-1])
604 gboolean partial, guint *tagCount)
610 if (!tags_array || !tags_array->len)
613 tag = g_new0(
TMTag, 1);
617 sort_options.
partial = partial;
619 sort_options.
first = TRUE;
628 sort_options.
first = FALSE;
629 first_pos = first - (
TMTag **)tags_array->pdata;
633 *tagCount = last - first + 1;
637 return (
TMTag **) first;
649 if (file_tags && file_tags->len)
652 gulong matching_line = 0;
654 for (i = 0; (i < file_tags->len); ++i)
657 if (tag && tag->
type & tag_types &&
661 matching_line = tag->
line;
673 if (tag->
lang == TM_PARSER_C || tag->
lang == TM_PARSER_CPP)
674 return sscanf(tag->
name,
"anon_%*[a-z]_%u%c", &i, &
dummy) == 1;
675 else if (tag->
lang == TM_PARSER_FORTRAN || tag->
lang == TM_PARSER_F77)
676 return sscanf(tag->
name,
"Structure#%u%c", &i, &
dummy) == 1 ||
677 sscanf(tag->
name,
"Interface#%u%c", &i, &
dummy) == 1 ||
678 sscanf(tag->
name,
"Enum#%u%c", &i, &
dummy) == 1;
689const char *tm_tag_type_name(
const TMTag *tag)
691 g_return_val_if_fail(tag,
NULL);
707static const char *tm_tag_impl_name(
TMTag *tag)
709 g_return_val_if_fail(tag,
NULL);
716static const char *tm_tag_access_name(
TMTag *tag)
718 g_return_val_if_fail(tag,
NULL);
734void tm_tag_print(
TMTag *tag, FILE *fp)
736 const char *laccess, *
impl, *type;
739 laccess = tm_tag_access_name(tag);
740 impl = tm_tag_impl_name(tag);
741 type = tm_tag_type_name(tag);
743 fprintf(fp,
"%s ", laccess);
745 fprintf(fp,
"%s ",
impl);
747 fprintf(fp,
"%s ", type);
751 fprintf(fp,
"%s::", tag->
scope);
752 fprintf(fp,
"%s", tag->
name);
754 fprintf(fp,
"%s", tag->
arglist);
766void tm_tags_array_print(GPtrArray *tags, FILE *fp)
770 if (!(tags && (tags->len > 0) && fp))
772 for (i = 0; i < tags->len; ++i)
774 tag =
TM_TAG(tags->pdata[i]);
775 tm_tag_print(tag, fp);
782gint tm_tag_scope_depth(
const TMTag *t)
789 for (s = t->
scope, depth = 0; s; s =
strstr(s, context_sep))
char * strstr(const char *str, const char *substr)
if(!stash_group_load_from_file(group, filename)) g_warning(_("Could not load keyfile %s!")
const GPtrArray * tags_array
The TMSourceFile structure represents the source file and its tags in the tag manager.
GPtrArray * tags_array
Sorted tag array obtained by parsing the object.
char * file_name
Full file name (inc.
The TMTag structure represents a single tag in the tag manager.
char * scope
Scope of tag.
char * inheritance
Parent classes.
char * var_type
Variable type (maps to struct for typedefs)
char * arglist
Argument list (functions/prototypes/macros)
TMSourceFile * file
These are tag attributes.
gulong line
Line number of the tag.
char access
Access type (public/protected/private/etc.)
char impl
Implementation (e.g.
gboolean local
Is the tag of local scope.
gchar tm_parser_get_tag_kind(TMTagType type, TMParserType lang)
const gchar * tm_parser_context_separator(TMParserType lang)
TMTagType tm_parser_get_tag_type(gchar kind, TMParserType lang)
@ tm_tag_undef_t
Unknown type.
const TMTag * tm_get_current_tag(GPtrArray *file_tags, const gulong line, const TMTagType tag_types)
GPtrArray * tm_tags_merge(GPtrArray *big_array, GPtrArray *small_array, TMTagAttrType *sort_attributes, gboolean unref_duplicates)
GType tm_tag_get_type(void)
Gets the GType for a TMTag.
static GPtrArray * merge(GPtrArray *big_array, GPtrArray *small_array, TMSortOptions *sort_options, gboolean unref_duplicates)
GPtrArray * tm_tags_extract(GPtrArray *tags_array, TMTagType tag_types)
void tm_tags_array_free(GPtrArray *tags_array, gboolean free_all)
void tm_tags_remove_file_tags(TMSourceFile *source_file, GPtrArray *tags_array)
static gint tm_tag_compare(gconstpointer ptr1, gconstpointer ptr2, gpointer user_data)
TMTag ** tm_tags_find(const GPtrArray *tags_array, const char *name, gboolean partial, guint *tagCount)
TMTag * tm_tag_ref(TMTag *tag)
gboolean tm_tag_is_anon(const TMTag *tag)
void tm_tag_unref(TMTag *tag)
gboolean tm_tags_equal(const TMTag *a, const TMTag *b)
static void tm_tag_destroy(TMTag *tag)
void tm_tags_prune(GPtrArray *tags_array)
void tm_tags_sort(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean dedup, gboolean unref_duplicates)
void tm_tags_dedup(GPtrArray *tags_array, TMTagAttrType *sort_attributes, gboolean unref_duplicates)
static gpointer binary_search(gpointer key, gpointer base, size_t nmemb, GCompareDataFunc compar, gpointer user_data)
static gint tag_search_cmp(gconstpointer ptr1, gconstpointer ptr2, gpointer user_data)
#define TAG_ACCESS_PROTECTED
Protected member.
#define TM_TAG(tag)
Use the TM_TAG() macro to cast a pointer to (TMTag *)
#define TAG_IMPL_VIRTUAL
Tag implementation type for functions.
#define TAG_ACCESS_PRIVATE
Private member.
#define TAG_ACCESS_PUBLIC
Tag access type for C++/Java member functions and variables.
TMTagAttrType
Tag Attributes.
@ tm_tag_attr_none_t
Undefined.
@ tm_tag_attr_vartype_t
Variable Type.
@ tm_tag_attr_name_t
Tag Name.
@ tm_tag_attr_file_t
File in which tag exists.
@ tm_tag_attr_scope_t
Scope of the tag.
@ tm_tag_attr_arglist_t
Argument list.
@ tm_tag_attr_line_t
Line number of tag.
@ tm_tag_attr_type_t
Tag Type.