bookloupe/counters.c
author ali <ali@juiblex.co.uk>
Tue Sep 24 07:22:18 2013 +0100 (2013-09-24)
changeset 109 f39394c9d41f
parent 94 3f655b1b0d93
child 111 f805130deb6f
child 123 ddb5ddba6ef3
permissions -rw-r--r--
Update documentation for 2.0.53
     1 #include <stdlib.h>
     2 #include <string.h>
     3 #include <glib.h>
     4 #include "bookloupe.h"
     5 #include "counters.h"
     6 
     7 struct matching_counter {
     8     int open,close;
     9 };
    10 
    11 static struct matching_counter *matching_counter_new(void)
    12 {
    13     return g_slice_new0(struct matching_counter);
    14 }
    15 
    16 static void matching_counter_free(struct matching_counter *counter)
    17 {
    18     g_slice_free(struct matching_counter,counter);
    19 }
    20 
    21 static gint compar_unichars(gconstpointer a,gconstpointer b,gpointer unused)
    22 {
    23     /*
    24      * Unicode code points only go up to 0x10FFFF and thus this cannot overflow.
    25      */
    26     return GPOINTER_TO_INT(a)-GPOINTER_TO_INT(b);
    27 }
    28 
    29 /*
    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.
    35  */
    36 static gpointer matching_key(gunichar ch)
    37 {
    38     gunichar mirrored;
    39     if (g_unichar_get_mirror_char(ch,&mirrored))
    40 	if (ch<mirrored)
    41 	    return GINT_TO_POINTER((gint)ch);
    42 	else
    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<0x4000 || ch-0x4000>=NO_SPECIAL_COUNTERS)
    49     {
    50 	g_warning("Matching pair not found for U+%04" G_GINT32_MODIFIER "X",ch);
    51 	return GINT_TO_POINTER((gint)ch);
    52     }
    53 }
    54 
    55 void increment_matching(struct counters *counters,gunichar ch,gboolean open)
    56 {
    57     gpointer key,orig_key;
    58     struct matching_counter *value;
    59     if (!counters->matching)
    60 	counters->matching=g_tree_new_full(compar_unichars,NULL,NULL,
    61 	  (GDestroyNotify)matching_counter_free);
    62     key=matching_key(ch);
    63     if (!g_tree_lookup_extended(counters->matching,key,&orig_key,
    64       (gpointer *)&value))
    65     {
    66 	value=matching_counter_new();
    67 	g_tree_insert(counters->matching,key,value);
    68     }
    69     if (open)
    70 	value->open++;
    71     else
    72 	value->close++;
    73 }
    74 
    75 int matching_count(const struct counters *counters,gunichar ch,gboolean open)
    76 {
    77     struct matching_counter *value;
    78     if (!counters->matching)
    79 	return 0;
    80     value=g_tree_lookup(counters->matching,matching_key(ch));
    81     if (!value)
    82 	return 0;
    83     return open?value->open:value->close;
    84 }
    85 
    86 /*
    87  * Return open count - closed count
    88  */
    89 int matching_difference(const struct counters *counters,gunichar ch)
    90 {
    91     struct matching_counter *value;
    92     if (!counters->matching)
    93 	return 0;
    94     value=g_tree_lookup(counters->matching,matching_key(ch));
    95     if (!value)
    96 	return 0;
    97     return value->open-value->close;
    98 }
    99 
   100 void counters_reset(struct counters *counters)
   101 {
   102     if (counters->matching)
   103 	g_tree_destroy(counters->matching);
   104     memset(counters,0,sizeof(*counters));
   105 }
   106 
   107 void counters_destroy(struct counters *counters)
   108 {
   109     if (counters->matching)
   110     {
   111 	g_tree_destroy(counters->matching);
   112 	counters->matching=NULL;
   113     }
   114 }