+typedef struct {
+ MonoString *name;
+ SharedCategory *cat;
+} CatSearch;
+
+static gboolean
+category_search (SharedHeader *header, void *data)
+{
+ CatSearch *search = data;
+ if (header->ftype == FTYPE_CATEGORY) {
+ SharedCategory *cat = (SharedCategory*)header;
+ if (mono_string_compare_ascii (search->name, cat->name) == 0) {
+ search->cat = cat;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static SharedCategory*
+find_custom_category (MonoString *name)
+{
+ CatSearch search;
+ search.name = name;
+ search.cat = NULL;
+ foreach_shared_item (category_search, &search);
+ return search.cat;
+}
+
+static gboolean
+category_collect (SharedHeader *header, void *data)
+{
+ GSList **list = data;
+ if (header->ftype == FTYPE_CATEGORY) {
+ *list = g_slist_prepend (*list, header);
+ }
+ return TRUE;
+}
+
+static GSList*
+get_custom_categories (void) {
+ GSList *list = NULL;
+ foreach_shared_item (category_collect, &list);
+ return list;
+}
+
+static char*
+custom_category_counters (SharedCategory* cat)
+{
+ char *p = cat->name + strlen (cat->name) + 1;
+ p += strlen (p) + 1; /* skip category help */
+ return p;
+}
+
+static SharedCounter*
+find_custom_counter (SharedCategory* cat, MonoString *name)
+{
+ int i;
+ char *p = custom_category_counters (cat);
+ for (i = 0; i < cat->num_counters; ++i) {
+ SharedCounter *counter = (SharedCounter*)p;
+ if (mono_string_compare_ascii (name, counter->name) == 0)
+ return counter;
+ p += 1 + strlen (p + 1) + 1; /* skip counter type and name */
+ p += strlen (p) + 1; /* skip counter help */
+ }
+ return NULL;
+}
+
+typedef struct {
+ unsigned int cat_offset;
+ SharedCategory* cat;
+ MonoString *instance;
+ SharedInstance* result;
+ GSList *list;
+} InstanceSearch;
+
+static gboolean
+instance_search (SharedHeader *header, void *data)
+{
+ InstanceSearch *search = data;
+ if (header->ftype == FTYPE_INSTANCE) {
+ SharedInstance *ins = (SharedInstance*)header;
+ if (search->cat_offset == ins->category_offset) {
+ if (search->instance) {
+ if (mono_string_compare_ascii (search->instance, ins->instance_name) == 0) {
+ search->result = ins;
+ return FALSE;
+ }
+ } else {
+ search->list = g_slist_prepend (search->list, ins);
+ }
+ }
+ }
+ return TRUE;
+}
+
+static SharedInstance*
+find_custom_instance (SharedCategory* cat, MonoString *instance)
+{
+ InstanceSearch search;
+ search.cat_offset = (char*)cat - (char*)shared_area;
+ search.cat = cat;
+ search.instance = instance;
+ search.list = NULL;
+ search.result = NULL;
+ foreach_shared_item (instance_search, &search);
+ return search.result;
+}
+
+static GSList*
+get_custom_instances_list (SharedCategory* cat)
+{
+ InstanceSearch search;
+ search.cat_offset = (char*)cat - (char*)shared_area;
+ search.cat = cat;
+ search.instance = NULL;
+ search.list = NULL;
+ search.result = NULL;
+ foreach_shared_item (instance_search, &search);
+ return search.list;
+}
+
+static char*
+custom_category_help (SharedCategory* cat)
+{
+ return cat->name + strlen (cat->name) + 1;
+}
+
+static const CounterDesc*
+get_counter_in_category (const CategoryDesc *desc, MonoString *counter)
+{
+ const CounterDesc *cdesc = &predef_counters [desc->first_counter];
+ const CounterDesc *end = &predef_counters [desc [1].first_counter];
+ for (; cdesc < end; ++cdesc) {
+ if (mono_string_compare_ascii (counter, cdesc->name) == 0)
+ return cdesc;
+ }
+ return NULL;
+}
+