1 /* Copyright (C) 2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Bruno Haible <haible@clisp.cons.org>, 2000.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 /* Construction of sparse 3-level tables.
21 See wchar-lookup.h or coll-lookup.h for their structure and the
24 Before including this file, set
25 TABLE to the name of the structure to be defined
26 ELEMENT to the type of every entry
27 DEFAULT to the default value for empty entries
28 ITERATE if you want the TABLE_iterate function to be defined
29 NO_FINALIZE if you don't want the TABLE_finalize function to be defined
34 void TABLE_init (struct TABLE *t);
35 ELEMENT TABLE_get (struct TABLE *t, uint32_t wc);
36 void TABLE_add (struct TABLE *t, uint32_t wc, ELEMENT value);
37 void TABLE_iterate (struct TABLE *t,
38 void (*fn) (uint32_t wc, ELEMENT value));
39 void TABLE_finalize (struct TABLE *t);
42 #define CONCAT(a,b) CONCAT1(a,b)
43 #define CONCAT1(a,b) a##b
50 /* Working representation. */
60 /* Compressed representation. */
65 /* Initialize. Assumes t->p and t->q have already been set. */
67 CONCAT(TABLE
,_init
) (struct TABLE
*t
)
70 t
->level1_alloc
= t
->level1_size
= 0;
72 t
->level2_alloc
= t
->level2_size
= 0;
74 t
->level3_alloc
= t
->level3_size
= 0;
77 /* Retrieve an entry. */
79 CONCAT(TABLE
,_get
) (struct TABLE
*t
, uint32_t wc
)
81 uint32_t index1
= wc
>> (t
->q
+ t
->p
);
82 if (index1
< t
->level1_size
)
84 uint32_t lookup1
= t
->level1
[index1
];
85 if (lookup1
!= ~((uint32_t) 0))
87 uint32_t index2
= ((wc
>> t
->p
) & ((1 << t
->q
) - 1))
89 uint32_t lookup2
= t
->level2
[index2
];
90 if (lookup2
!= ~((uint32_t) 0))
92 uint32_t index3
= (wc
& ((1 << t
->p
) - 1))
94 ELEMENT lookup3
= t
->level3
[index3
];
105 CONCAT(TABLE
,_add
) (struct TABLE
*t
, uint32_t wc
, ELEMENT value
)
107 uint32_t index1
= wc
>> (t
->q
+ t
->p
);
108 uint32_t index2
= (wc
>> t
->p
) & ((1 << t
->q
) - 1);
109 uint32_t index3
= wc
& ((1 << t
->p
) - 1);
112 if (value
== CONCAT(TABLE
,_get
) (t
, wc
))
115 if (index1
>= t
->level1_size
)
117 if (index1
>= t
->level1_alloc
)
119 size_t alloc
= 2 * t
->level1_alloc
;
122 t
->level1
= (uint32_t *) xrealloc ((char *) t
->level1
,
123 alloc
* sizeof (uint32_t));
124 t
->level1_alloc
= alloc
;
126 while (index1
>= t
->level1_size
)
127 t
->level1
[t
->level1_size
++] = ~((uint32_t) 0);
130 if (t
->level1
[index1
] == ~((uint32_t) 0))
132 if (t
->level2_size
== t
->level2_alloc
)
134 size_t alloc
= 2 * t
->level2_alloc
+ 1;
135 t
->level2
= (uint32_t *) xrealloc ((char *) t
->level2
,
136 (alloc
<< t
->q
) * sizeof (uint32_t));
137 t
->level2_alloc
= alloc
;
139 i1
= t
->level2_size
<< t
->q
;
140 i2
= (t
->level2_size
+ 1) << t
->q
;
141 for (i
= i1
; i
< i2
; i
++)
142 t
->level2
[i
] = ~((uint32_t) 0);
143 t
->level1
[index1
] = t
->level2_size
++;
146 index2
+= t
->level1
[index1
] << t
->q
;
148 if (t
->level2
[index2
] == ~((uint32_t) 0))
150 if (t
->level3_size
== t
->level3_alloc
)
152 size_t alloc
= 2 * t
->level3_alloc
+ 1;
153 t
->level3
= (ELEMENT
*) xrealloc ((char *) t
->level3
,
154 (alloc
<< t
->p
) * sizeof (ELEMENT
));
155 t
->level3_alloc
= alloc
;
157 i1
= t
->level3_size
<< t
->p
;
158 i2
= (t
->level3_size
+ 1) << t
->p
;
159 for (i
= i1
; i
< i2
; i
++)
160 t
->level3
[i
] = DEFAULT
;
161 t
->level2
[index2
] = t
->level3_size
++;
164 index3
+= t
->level2
[index2
] << t
->p
;
166 t
->level3
[index3
] = value
;
170 /* Apply a function to all entries in the table. */
172 CONCAT(TABLE
,_iterate
) (struct TABLE
*t
,
173 void (*fn
) (uint32_t wc
, ELEMENT value
))
176 for (index1
= 0; index1
< t
->level1_size
; index1
++)
178 uint32_t lookup1
= t
->level1
[index1
];
179 if (lookup1
!= ~((uint32_t) 0))
181 uint32_t lookup1_shifted
= lookup1
<< t
->q
;
183 for (index2
= 0; index2
< (1 << t
->q
); index2
++)
185 uint32_t lookup2
= t
->level2
[index2
+ lookup1_shifted
];
186 if (lookup2
!= ~((uint32_t) 0))
188 uint32_t lookup2_shifted
= lookup2
<< t
->p
;
190 for (index3
= 0; index3
< (1 << t
->p
); index3
++)
192 ELEMENT lookup3
= t
->level3
[index3
+ lookup2_shifted
];
193 if (lookup3
!= DEFAULT
)
194 fn ((((index1
<< t
->q
) + index2
) << t
->p
) + index3
,
205 /* Finalize and shrink. */
207 CONCAT(TABLE
,_finalize
) (struct TABLE
*t
)
210 uint32_t reorder3
[t
->level3_size
];
211 uint32_t reorder2
[t
->level2_size
];
212 uint32_t level1_offset
, level2_offset
, level3_offset
, last_offset
;
214 /* Uniquify level3 blocks. */
216 for (j
= 0; j
< t
->level3_size
; j
++)
218 for (i
= 0; i
< k
; i
++)
219 if (memcmp (&t
->level3
[i
<< t
->p
], &t
->level3
[j
<< t
->p
],
220 (1 << t
->p
) * sizeof (ELEMENT
)) == 0)
222 /* Relocate block j to block i. */
227 memcpy (&t
->level3
[i
<< t
->p
], &t
->level3
[j
<< t
->p
],
228 (1 << t
->p
) * sizeof (ELEMENT
));
234 for (i
= 0; i
< (t
->level2_size
<< t
->q
); i
++)
235 if (t
->level2
[i
] != ~((uint32_t) 0))
236 t
->level2
[i
] = reorder3
[t
->level2
[i
]];
238 /* Uniquify level2 blocks. */
240 for (j
= 0; j
< t
->level2_size
; j
++)
242 for (i
= 0; i
< k
; i
++)
243 if (memcmp (&t
->level2
[i
<< t
->q
], &t
->level2
[j
<< t
->q
],
244 (1 << t
->q
) * sizeof (uint32_t)) == 0)
246 /* Relocate block j to block i. */
251 memcpy (&t
->level2
[i
<< t
->q
], &t
->level2
[j
<< t
->q
],
252 (1 << t
->q
) * sizeof (uint32_t));
258 for (i
= 0; i
< t
->level1_size
; i
++)
259 if (t
->level1
[i
] != ~((uint32_t) 0))
260 t
->level1
[i
] = reorder2
[t
->level1
[i
]];
262 /* Create and fill the resulting compressed representation. */
264 5 * sizeof (uint32_t)
265 + t
->level1_size
* sizeof (uint32_t)
266 + (t
->level2_size
<< t
->q
) * sizeof (uint32_t)
267 + (t
->level3_size
<< t
->p
) * sizeof (ELEMENT
);
268 t
->result_size
= (last_offset
+ 3) & ~3ul;
269 t
->result
= (char *) xmalloc (t
->result_size
);
272 5 * sizeof (uint32_t);
274 5 * sizeof (uint32_t)
275 + t
->level1_size
* sizeof (uint32_t);
277 5 * sizeof (uint32_t)
278 + t
->level1_size
* sizeof (uint32_t)
279 + (t
->level2_size
<< t
->q
) * sizeof (uint32_t);
281 ((uint32_t *) t
->result
)[0] = t
->q
+ t
->p
;
282 ((uint32_t *) t
->result
)[1] = t
->level1_size
;
283 ((uint32_t *) t
->result
)[2] = t
->p
;
284 ((uint32_t *) t
->result
)[3] = (1 << t
->q
) - 1;
285 ((uint32_t *) t
->result
)[4] = (1 << t
->p
) - 1;
287 for (i
= 0; i
< t
->level1_size
; i
++)
288 ((uint32_t *) (t
->result
+ level1_offset
))[i
] =
289 (t
->level1
[i
] == ~((uint32_t) 0)
291 : (t
->level1
[i
] << t
->q
) * sizeof (uint32_t) + level2_offset
);
293 for (i
= 0; i
< (t
->level2_size
<< t
->q
); i
++)
294 ((uint32_t *) (t
->result
+ level2_offset
))[i
] =
295 (t
->level2
[i
] == ~((uint32_t) 0)
297 : (t
->level2
[i
] << t
->p
) * sizeof (ELEMENT
) + level3_offset
);
299 for (i
= 0; i
< (t
->level3_size
<< t
->p
); i
++)
300 ((ELEMENT
*) (t
->result
+ level3_offset
))[i
] = t
->level3
[i
];
302 if (last_offset
< t
->result_size
)
303 memset (t
->result
+ last_offset
, 0, t
->result_size
- last_offset
);
305 if (t
->level1_alloc
> 0)
307 if (t
->level2_alloc
> 0)
309 if (t
->level3_alloc
> 0)