7 struct matching_counter {
11 static struct matching_counter *matching_counter_new(void)
13 return g_slice_new0(struct matching_counter);
16 static void matching_counter_free(struct matching_counter *counter)
18 g_slice_free(struct matching_counter,counter);
21 static gint compar_unichars(gconstpointer a,gconstpointer b,gpointer unused)
24 * Unicode code points only go up to 0x10FFFF and thus this cannot overflow.
26 return GPOINTER_TO_INT(a)-GPOINTER_TO_INT(b);
30 * For matching characters, we maintain a count of the opens and closes.
31 * In the simplest case, we are dealing with a matching pair such as [ and ]
32 * where there is a 1:1 mapping between an instance of [ with an open and
33 * between an instance of ] with a close. matching_ket() is
34 * responsible for selecting an arbitary base character of a matching pair.
36 static gpointer matching_key(gunichar ch)
39 if (g_unichar_get_mirror_char(ch,&mirrored))
41 return GINT_TO_POINTER((gint)ch);
43 return GINT_TO_POINTER((gint)mirrored);
44 else if (ch==CHAR_SQUOTE || ch==CHAR_OPEN_SQUOTE)
45 return GINT_TO_POINTER((gint)CHAR_SQUOTE);
46 else if (ch==CHAR_LS_QUOTE || ch==CHAR_RS_QUOTE)
47 return GINT_TO_POINTER((gint)CHAR_LS_QUOTE);
48 else if (ch==CHAR_LD_QUOTE || ch==CHAR_RD_QUOTE)
49 return GINT_TO_POINTER((gint)CHAR_LD_QUOTE);
50 else if (ch==CHAR_DQUOTE)
51 return GINT_TO_POINTER((gint)ch);
52 else if (ch<0x4000 || ch-0x4000>=NO_SPECIAL_COUNTERS)
53 g_warning("Matching pair not found for U+%04" G_GINT32_MODIFIER "X",ch);
54 return GINT_TO_POINTER((gint)ch);
57 void increment_matching(struct counters *counters,gunichar ch,gboolean open)
59 gpointer key,orig_key;
60 struct matching_counter *value;
61 if (!counters->matching)
62 counters->matching=g_tree_new_full(compar_unichars,NULL,NULL,
63 (GDestroyNotify)matching_counter_free);
65 if (!g_tree_lookup_extended(counters->matching,key,&orig_key,
68 value=matching_counter_new();
69 g_tree_insert(counters->matching,key,value);
77 int matching_count(const struct counters *counters,gunichar ch,gboolean open)
79 struct matching_counter *value;
80 if (!counters->matching)
82 value=g_tree_lookup(counters->matching,matching_key(ch));
85 return open?value->open:value->close;
89 * Return open count - closed count
91 int matching_difference(const struct counters *counters,gunichar ch)
93 struct matching_counter *value;
94 if (!counters->matching)
96 value=g_tree_lookup(counters->matching,matching_key(ch));
99 return value->open-value->close;
102 void counters_reset(struct counters *counters)
104 if (counters->matching)
105 g_tree_destroy(counters->matching);
106 memset(counters,0,sizeof(*counters));
109 void counters_destroy(struct counters *counters)
111 if (counters->matching)
113 g_tree_destroy(counters->matching);
114 counters->matching=NULL;