1 /* Part of XPCE --- The SWI-Prolog GUI toolkit
2
3 Author: Jan Wielemaker and Anjo Anjewierden
4 E-mail: wielemak@science.uva.nl
5 WWW: http://www.swi-prolog.org/projects/xpce/
6 Copyright (c) 2011-2016, University of Amsterdam
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12
13 1. Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16 2. Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 typedef struct asymbol *ASymbol;
36 typedef struct table *Table;
37
38 struct asymbol
39 { atom_t atom;
40 PceName name;
41 ASymbol next;
42 };
43
44 struct table
45 { ASymbol *symbols;
46 int allocated;
47 int size;
48 int mask;
49 };
50
51 static struct table atom_to_name;
52 static struct table name_to_atom;
53
54 #define AtomKey(t, a) (int)(((a)>>5) & (t)->mask)
55 #define NameKey(t, a) (int)(((uintptr_t)(a)>>2) & (t)->mask)
56
57 static void
rehashTable(Table t,int aton)58 rehashTable(Table t, int aton)
59 { ASymbol *old = t->symbols;
60 int oldentries = t->allocated;
61 int n;
62
63 t->allocated *= 2;
64 t->mask = t->allocated - 1;
65 t->symbols = malloc(t->allocated * sizeof(ASymbol));
66 memset(t->symbols, 0, t->allocated * sizeof(ASymbol));
67
68 for(n=0; n<oldentries; n++)
69 { ASymbol s = old[n];
70 ASymbol n;
71
72 for( ; s; s = n )
73 { int k;
74
75 n = s->next;
76
77 if ( aton )
78 k = AtomKey(t, s->atom);
79 else
80 k = NameKey(t, s->name);
81
82 s->next = t->symbols[k];
83 t->symbols[k] = s;
84 }
85 }
86
87 free(old);
88 }
89
90 static PceName
atomToName(atom_t a)91 atomToName(atom_t a)
92 { int k = AtomKey(&atom_to_name, a);
93 ASymbol s = atom_to_name.symbols[k];
94 PceName name;
95 size_t len;
96 const char *textA;
97 const wchar_t *textW;
98
99 for( ; s; s = s->next )
100 { if ( s->atom == a )
101 return s->name;
102 }
103
104 PL_register_atom(a);
105 if ( (textA = PL_atom_nchars(a, &len)) )
106 { name = cToPceName_nA(textA, len);
107 } else if ( (textW = PL_atom_wchars(a, &len)) )
108 { name = cToPceName_nW(textW, len);
109 } else
110 { assert(0);
111 return NULL;
112 }
113
114 s = pceAlloc(sizeof(struct asymbol));
115 s->atom = a;
116 s->name = name;
117 s->next = atom_to_name.symbols[k];
118 atom_to_name.symbols[k] = s;
119 if ( ++atom_to_name.size > 2*atom_to_name.allocated )
120 rehashTable(&atom_to_name, TRUE);
121
122 return name;
123 }
124
125
126 static atom_t
CachedNameToAtom(PceName name)127 CachedNameToAtom(PceName name)
128 { int k = NameKey(&name_to_atom, name);
129 ASymbol s = name_to_atom.symbols[k];
130 atom_t a;
131 size_t len;
132 const char *textA;
133 const wchar_t *textW;
134
135 for( ; s; s = s->next )
136 { if ( s->name == name )
137 return s->atom;
138 }
139
140 if ( (textA = pceCharArrayToCA(name, &len)) )
141 { a = PL_new_atom_nchars(len, textA);
142 } else if ( (textW = pceCharArrayToCW(name, &len)) )
143 { a = PL_new_atom_wchars(len, textW);
144 } else
145 { assert(0);
146 return 0;
147 }
148
149 s = pceAlloc(sizeof(struct asymbol));
150 s->atom = a;
151 s->name = name;
152 s->next = name_to_atom.symbols[k];
153 name_to_atom.symbols[k] = s;
154 if ( ++name_to_atom.size > 2*name_to_atom.allocated )
155 rehashTable(&name_to_atom, FALSE);
156
157 return a;
158 }
159
160
161 static void
initTable(Table t)162 initTable(Table t)
163 { t->allocated = 1024;
164 t->size = 0;
165 t->mask = t->allocated-1;
166 t->symbols = malloc(t->allocated * sizeof(ASymbol));
167 memset(t->symbols, 0, t->allocated * sizeof(ASymbol));
168 }
169
170
171 static void
initNameAtomTable()172 initNameAtomTable()
173 { initTable(&atom_to_name);
174 initTable(&name_to_atom);
175 }
176