Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / libnrtype / nr-type-primitives.cpp
1 #define __NR_TYPE_PRIMITIVES_C__
3 /*
4  * Typeface and script library
5  *
6  * Authors:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *
9  * This code is in public domain
10  */
12 /* This should be enough for approximately 10000 fonts */
13 #define NR_DICTSIZE 2777
15 #include <stdlib.h>
16 #include <string.h>
17 #include <glib/gmem.h>
18 #include <libnr/nr-macros.h>
19 #include "nr-type-primitives.h"
21 /**
22  * An entry in a list of key->value pairs
23  */
24 struct NRTDEntry {
25         NRTDEntry *next;
26         const gchar *key;
27         void *val;
28 };
30 /**
31  * Type Dictionary, consisting of size number of key-value entries
32  */
33 struct NRTypeDict {
34         unsigned int size;
35         NRTDEntry **entries;
36 };
38 static NRTDEntry *nr_td_entry_new (void);
40 /**
41  * Calls the destructor for each item in list
42  */
43 void
44 nr_name_list_release (NRNameList *list)
45 {
46         if (list->destructor) {
47                 list->destructor (list);
48         }
49 }
51 void
52 nr_style_list_release (NRStyleList *list)
53 {
54         if (list->destructor) {
55                 list->destructor (list);
56         }
57 }
59 /**
60  * Creates a new typeface dictionary of size NR_DICTSIZE
61  * and initalizes all the entries to NULL
62  */
63 NRTypeDict *
64 nr_type_dict_new (void)
65 {
66         NRTypeDict *td;
67         int i;
69         td = g_new (NRTypeDict, 1);
71         td->size = NR_DICTSIZE;
72         td->entries = g_new (NRTDEntry *, td->size);
73         for (i = 0; i < NR_DICTSIZE; i++) {
74                 td->entries[i] = NULL;
75         }
77         return td;
78 }
80 /**
81  * Hashes a string and returns the int
82  */
83 static unsigned int
84 nr_str_hash (const gchar *p)
85 {
86         unsigned int h;
88         h = *p;
90         if (h != 0) {
91                 for (p += 1; *p; p++) h = (h << 5) - h + *p;
92         }
94         return h;
95 }
97 /**
98  * Inserts a key/value into a typeface dictionary
99  */
100 void
101 nr_type_dict_insert (NRTypeDict *td, const gchar *key, void *val)
103         if (key) {
104                 NRTDEntry *tde;
105                 unsigned int hval;
107                 hval = nr_str_hash (key) % td->size;
109                 for (tde = td->entries[hval]; tde; tde = tde->next) {
110                         if (!strcmp (key, tde->key)) {
111                                 tde->val = val;
112                                 return;
113                         }
114                 }
116                 tde = nr_td_entry_new ();
117                 tde->next = td->entries[hval];
118                 tde->key = key;
119                 tde->val = val;
120                 td->entries[hval] = tde;
121         }
124 /**
125  * Looks up the given key from the typeface dictionary
126  */
127 void *
128 nr_type_dict_lookup (NRTypeDict *td, const gchar *key)
130         if (key) {
131                 NRTDEntry *tde;
132                 unsigned int hval;
133                 hval = nr_str_hash (key) % td->size;
134                 for (tde = td->entries[hval]; tde; tde = tde->next) {
135                         if (!strcmp (key, tde->key)) return tde->val;
136                 }
137         }
139         return NULL;
142 #define NR_TDE_BLOCK_SIZE 32
144 static NRTDEntry *nr_tde_free_list;
146 /**
147  * Creates a new TDEntry
148  */
149 static NRTDEntry *
150 nr_td_entry_new (void)
152         NRTDEntry *tde;
154         if (!nr_tde_free_list) {
155                 int i;
156                 nr_tde_free_list = g_new (NRTDEntry, NR_TDE_BLOCK_SIZE);
157                 for (i = 0; i < (NR_TDE_BLOCK_SIZE - 1); i++) {
158                         nr_tde_free_list[i].next = nr_tde_free_list + i + 1;
159                 }
160                 nr_tde_free_list[i].next = NULL;
161         }
163         tde = nr_tde_free_list;
164         nr_tde_free_list = tde->next;
166         return tde;