1 /* Copyright (C) 2000-2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Bruno Haible <haible@clisp.cons.org>, 2000.
6 NOTE: The canonical source of this file is maintained with the GNU C Library.
7 Bugs can be reported to bug-glibc@gnu.org.
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
24 /* Construction of sparse 3-level tables.
25 See wchar-lookup.h or coll-lookup.h for their structure and the
28 Before including this file, set
29 TABLE to the name of the structure to be defined
30 ELEMENT to the type of every entry
31 DEFAULT to the default value for empty entries
32 ITERATE if you want the TABLE_iterate function to be defined
33 NO_FINALIZE if you don't want the TABLE_finalize function to be defined
38 void TABLE_init (struct TABLE *t);
39 ELEMENT TABLE_get (struct TABLE *t, uint32_t wc);
40 void TABLE_add (struct TABLE *t, uint32_t wc, ELEMENT value);
41 void TABLE_iterate (struct TABLE *t,
42 void (*fn) (uint32_t wc, ELEMENT value));
43 void TABLE_finalize (struct TABLE *t);
46 #define CONCAT(a,b) CONCAT1(a,b)
47 #define CONCAT1(a,b) a##b
54 /* Working representation. */
64 /* Compressed representation. */
69 /* Initialize. Assumes t->p and t->q have already been set. */
71 CONCAT(TABLE
,_init
) (struct TABLE
*t
)
74 t
->level1_alloc
= t
->level1_size
= 0;
76 t
->level2_alloc
= t
->level2_size
= 0;
78 t
->level3_alloc
= t
->level3_size
= 0;
81 /* Marker for an empty slot. This has the value 0xFFFFFFFF, regardless
82 whether 'int' is 16 bit, 32 bit, or 64 bit. */
83 #define EMPTY ((uint32_t) ~0)
85 /* Retrieve an entry. */
87 CONCAT(TABLE
,_get
) (struct TABLE
*t
, uint32_t wc
)
89 uint32_t index1
= wc
>> (t
->q
+ t
->p
);
90 if (index1
< t
->level1_size
)
92 uint32_t lookup1
= t
->level1
[index1
];
95 uint32_t index2
= ((wc
>> t
->p
) & ((1 << t
->q
) - 1))
97 uint32_t lookup2
= t
->level2
[index2
];
100 uint32_t index3
= (wc
& ((1 << t
->p
) - 1))
102 ELEMENT lookup3
= t
->level3
[index3
];
113 CONCAT(TABLE
,_add
) (struct TABLE
*t
, uint32_t wc
, ELEMENT value
)
115 uint32_t index1
= wc
>> (t
->q
+ t
->p
);
116 uint32_t index2
= (wc
>> t
->p
) & ((1 << t
->q
) - 1);
117 uint32_t index3
= wc
& ((1 << t
->p
) - 1);
120 if (value
== CONCAT(TABLE
,_get
) (t
, wc
))
123 if (index1
>= t
->level1_size
)
125 if (index1
>= t
->level1_alloc
)
127 size_t alloc
= 2 * t
->level1_alloc
;
130 t
->level1
= (uint32_t *) xrealloc ((char *) t
->level1
,
131 alloc
* sizeof (uint32_t));
132 t
->level1_alloc
= alloc
;
134 while (index1
>= t
->level1_size
)
135 t
->level1
[t
->level1_size
++] = EMPTY
;
138 if (t
->level1
[index1
] == EMPTY
)
140 if (t
->level2_size
== t
->level2_alloc
)
142 size_t alloc
= 2 * t
->level2_alloc
+ 1;
143 t
->level2
= (uint32_t *) xrealloc ((char *) t
->level2
,
144 (alloc
<< t
->q
) * sizeof (uint32_t));
145 t
->level2_alloc
= alloc
;
147 i1
= t
->level2_size
<< t
->q
;
148 i2
= (t
->level2_size
+ 1) << t
->q
;
149 for (i
= i1
; i
< i2
; i
++)
150 t
->level2
[i
] = EMPTY
;
151 t
->level1
[index1
] = t
->level2_size
++;
154 index2
+= t
->level1
[index1
] << t
->q
;
156 if (t
->level2
[index2
] == EMPTY
)
158 if (t
->level3_size
== t
->level3_alloc
)
160 size_t alloc
= 2 * t
->level3_alloc
+ 1;
161 t
->level3
= (ELEMENT
*) xrealloc ((char *) t
->level3
,
162 (alloc
<< t
->p
) * sizeof (ELEMENT
));
163 t
->level3_alloc
= alloc
;
165 i1
= t
->level3_size
<< t
->p
;
166 i2
= (t
->level3_size
+ 1) << t
->p
;
167 for (i
= i1
; i
< i2
; i
++)
168 t
->level3
[i
] = DEFAULT
;
169 t
->level2
[index2
] = t
->level3_size
++;
172 index3
+= t
->level2
[index2
] << t
->p
;
174 t
->level3
[index3
] = value
;
178 /* Apply a function to all entries in the table. */
180 CONCAT(TABLE
,_iterate
) (struct TABLE
*t
,
181 void (*fn
) (uint32_t wc
, ELEMENT value
))
184 for (index1
= 0; index1
< t
->level1_size
; index1
++)
186 uint32_t lookup1
= t
->level1
[index1
];
187 if (lookup1
!= EMPTY
)
189 uint32_t lookup1_shifted
= lookup1
<< t
->q
;
191 for (index2
= 0; index2
< (1 << t
->q
); index2
++)
193 uint32_t lookup2
= t
->level2
[index2
+ lookup1_shifted
];
194 if (lookup2
!= EMPTY
)
196 uint32_t lookup2_shifted
= lookup2
<< t
->p
;
198 for (index3
= 0; index3
< (1 << t
->p
); index3
++)
200 ELEMENT lookup3
= t
->level3
[index3
+ lookup2_shifted
];
201 if (lookup3
!= DEFAULT
)
202 fn ((((index1
<< t
->q
) + index2
) << t
->p
) + index3
,
213 /* Finalize and shrink. */
215 CONCAT(TABLE
,_finalize
) (struct TABLE
*t
)
218 uint32_t reorder3
[t
->level3_size
];
219 uint32_t reorder2
[t
->level2_size
];
220 uint32_t level1_offset
, level2_offset
, level3_offset
, last_offset
;
222 /* Uniquify level3 blocks. */
224 for (j
= 0; j
< t
->level3_size
; j
++)
226 for (i
= 0; i
< k
; i
++)
227 if (memcmp (&t
->level3
[i
<< t
->p
], &t
->level3
[j
<< t
->p
],
228 (1 << t
->p
) * sizeof (ELEMENT
)) == 0)
230 /* Relocate block j to block i. */
235 memcpy (&t
->level3
[i
<< t
->p
], &t
->level3
[j
<< t
->p
],
236 (1 << t
->p
) * sizeof (ELEMENT
));
242 for (i
= 0; i
< (t
->level2_size
<< t
->q
); i
++)
243 if (t
->level2
[i
] != EMPTY
)
244 t
->level2
[i
] = reorder3
[t
->level2
[i
]];
246 /* Uniquify level2 blocks. */
248 for (j
= 0; j
< t
->level2_size
; j
++)
250 for (i
= 0; i
< k
; i
++)
251 if (memcmp (&t
->level2
[i
<< t
->q
], &t
->level2
[j
<< t
->q
],
252 (1 << t
->q
) * sizeof (uint32_t)) == 0)
254 /* Relocate block j to block i. */
259 memcpy (&t
->level2
[i
<< t
->q
], &t
->level2
[j
<< t
->q
],
260 (1 << t
->q
) * sizeof (uint32_t));
266 for (i
= 0; i
< t
->level1_size
; i
++)
267 if (t
->level1
[i
] != EMPTY
)
268 t
->level1
[i
] = reorder2
[t
->level1
[i
]];
270 /* Create and fill the resulting compressed representation. */
272 5 * sizeof (uint32_t)
273 + t
->level1_size
* sizeof (uint32_t)
274 + (t
->level2_size
<< t
->q
) * sizeof (uint32_t)
275 + (t
->level3_size
<< t
->p
) * sizeof (ELEMENT
);
276 t
->result_size
= (last_offset
+ 3) & ~3ul;
277 t
->result
= (char *) xmalloc (t
->result_size
);
280 5 * sizeof (uint32_t);
282 5 * sizeof (uint32_t)
283 + t
->level1_size
* sizeof (uint32_t);
285 5 * sizeof (uint32_t)
286 + t
->level1_size
* sizeof (uint32_t)
287 + (t
->level2_size
<< t
->q
) * sizeof (uint32_t);
289 ((uint32_t *) t
->result
)[0] = t
->q
+ t
->p
;
290 ((uint32_t *) t
->result
)[1] = t
->level1_size
;
291 ((uint32_t *) t
->result
)[2] = t
->p
;
292 ((uint32_t *) t
->result
)[3] = (1 << t
->q
) - 1;
293 ((uint32_t *) t
->result
)[4] = (1 << t
->p
) - 1;
295 for (i
= 0; i
< t
->level1_size
; i
++)
296 ((uint32_t *) (t
->result
+ level1_offset
))[i
] =
297 (t
->level1
[i
] == EMPTY
299 : (t
->level1
[i
] << t
->q
) * sizeof (uint32_t) + level2_offset
);
301 for (i
= 0; i
< (t
->level2_size
<< t
->q
); i
++)
302 ((uint32_t *) (t
->result
+ level2_offset
))[i
] =
303 (t
->level2
[i
] == EMPTY
305 : (t
->level2
[i
] << t
->p
) * sizeof (ELEMENT
) + level3_offset
);
307 for (i
= 0; i
< (t
->level3_size
<< t
->p
); i
++)
308 ((ELEMENT
*) (t
->result
+ level3_offset
))[i
] = t
->level3
[i
];
310 if (last_offset
< t
->result_size
)
311 memset (t
->result
+ last_offset
, 0, t
->result_size
- last_offset
);
313 if (t
->level1_alloc
> 0)
315 if (t
->level2_alloc
> 0)
317 if (t
->level3_alloc
> 0)