bookloupe/counters.c
changeset 94 3f655b1b0d93
child 103 adc06e9e8470
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/bookloupe/counters.c	Sat Sep 21 18:28:40 2013 +0100
     1.3 @@ -0,0 +1,106 @@
     1.4 +#include <stdlib.h>
     1.5 +#include <glib.h>
     1.6 +#include "bookloupe.h"
     1.7 +#include "counters.h"
     1.8 +
     1.9 +struct matching_counter {
    1.10 +    int open,close;
    1.11 +};
    1.12 +
    1.13 +static struct matching_counter *matching_counter_new(void)
    1.14 +{
    1.15 +    return g_slice_new0(struct matching_counter);
    1.16 +}
    1.17 +
    1.18 +static void matching_counter_free(struct matching_counter *counter)
    1.19 +{
    1.20 +    g_slice_free(struct matching_counter,counter);
    1.21 +}
    1.22 +
    1.23 +static gint compar_unichars(gconstpointer a,gconstpointer b,gpointer unused)
    1.24 +{
    1.25 +    /*
    1.26 +     * Unicode code points only go up to 0x10FFFF and thus this cannot overflow.
    1.27 +     */
    1.28 +    return GPOINTER_TO_INT(a)-GPOINTER_TO_INT(b);
    1.29 +}
    1.30 +
    1.31 +/*
    1.32 + * For matching characters, we maintain a count of the opens and closes.
    1.33 + * In the simplest case, we are dealing with a matching pair such as [ and ]
    1.34 + * where there is a 1:1 mapping between an instance of [ with an open and
    1.35 + * between an instance of ] with a close. matching_ket() is
    1.36 + * responsible for selecting an arbitary base character of a matching pair.
    1.37 + */
    1.38 +static gpointer matching_key(gunichar ch)
    1.39 +{
    1.40 +    gunichar mirrored;
    1.41 +    if (g_unichar_get_mirror_char(ch,&mirrored))
    1.42 +	if (ch<mirrored)
    1.43 +	    return GINT_TO_POINTER((gint)ch);
    1.44 +	else
    1.45 +	    return GINT_TO_POINTER((gint)mirrored);
    1.46 +    else if (ch==CHAR_SQUOTE || ch==CHAR_OPEN_SQUOTE)
    1.47 +	return GINT_TO_POINTER((gint)CHAR_SQUOTE);
    1.48 +    else if (ch==CHAR_LS_QUOTE || ch==CHAR_RS_QUOTE)
    1.49 +	return GINT_TO_POINTER((gint)CHAR_LS_QUOTE);
    1.50 +    else
    1.51 +    {
    1.52 +	g_warning("Matching pair not found for U+%04"G_GINT32_FORMAT"X",ch);
    1.53 +	return GINT_TO_POINTER((gint)ch);
    1.54 +    }
    1.55 +}
    1.56 +
    1.57 +void increment_matching(struct counters *counters,gunichar ch,gboolean open)
    1.58 +{
    1.59 +    gpointer key,orig_key;
    1.60 +    struct matching_counter *value;
    1.61 +    if (!counters->matching)
    1.62 +	counters->matching=g_tree_new_full(compar_unichars,NULL,NULL,
    1.63 +	  (GDestroyNotify)matching_counter_free);
    1.64 +    key=matching_key(ch);
    1.65 +    if (!g_tree_lookup_extended(counters->matching,key,&orig_key,
    1.66 +      (gpointer *)&value))
    1.67 +    {
    1.68 +	value=matching_counter_new();
    1.69 +	g_tree_insert(counters->matching,key,value);
    1.70 +    }
    1.71 +    if (open)
    1.72 +	value->open++;
    1.73 +    else
    1.74 +	value->close++;
    1.75 +}
    1.76 +
    1.77 +int matching_count(const struct counters *counters,gunichar ch,gboolean open)
    1.78 +{
    1.79 +    struct matching_counter *value;
    1.80 +    if (!counters->matching)
    1.81 +	return 0;
    1.82 +    value=g_tree_lookup(counters->matching,matching_key(ch));
    1.83 +    if (!value)
    1.84 +	return 0;
    1.85 +    return open?value->open:value->close;
    1.86 +}
    1.87 +
    1.88 +/*
    1.89 + * Return open count - closed count
    1.90 + */
    1.91 +int matching_difference(const struct counters *counters,gunichar ch)
    1.92 +{
    1.93 +    struct matching_counter *value;
    1.94 +    if (!counters->matching)
    1.95 +	return 0;
    1.96 +    value=g_tree_lookup(counters->matching,matching_key(ch));
    1.97 +    if (!value)
    1.98 +	return 0;
    1.99 +    return value->open-value->close;
   1.100 +}
   1.101 +
   1.102 +void counters_destroy(struct counters *counters)
   1.103 +{
   1.104 +    if (counters->matching)
   1.105 +    {
   1.106 +	g_tree_destroy(counters->matching);
   1.107 +	counters->matching=NULL;
   1.108 +    }
   1.109 +}