@@ -214,57 +214,26 @@ static void ext_tolower(char *ext, size_t len) {
214214 }
215215}
216216
217- /**
218- * The "smart case" algorithm.
219- *
220- * @param ext
221- * The current extension being added.
222- * @param prev
223- * The previous case-sensitive match, if any, for the same extension.
224- * @param iprev
225- * The previous case-insensitive match, if any, for the same extension.
226- * @return
227- * Whether this extension should become case-sensitive.
228- */
229- static bool ext_case_sensitive (struct ext_color * ext , struct ext_color * prev , struct ext_color * iprev ) {
230- // This is the first case-insensitive occurrence of this extension, e.g.
231- //
232- // *.gz=01;31:*.tar.gz=01;33
233- if (!iprev ) {
234- bfs_assert (!prev );
235- return false;
236- }
237-
238- // If the last version of this extension is already case-sensitive,
239- // this one should be too, e.g.
240- //
241- // *.tar.gz=01;31:*.TAR.GZ=01;32:*.TAR.GZ=01;33
242- if (iprev -> case_sensitive ) {
243- return true;
244- }
245-
246- // The case matches the last occurrence exactly, e.g.
247- //
248- // *.tar.gz=01;31:*.tar.gz=01;33
249- if (iprev == prev ) {
250- return false;
217+ /** Insert an extension into a trie. */
218+ static int insert_ext (struct trie * trie , struct ext_color * ext ) {
219+ // A later *.x should override any earlier *.x, *.y.x, etc.
220+ struct trie_leaf * leaf ;
221+ while ((leaf = trie_find_postfix (trie , ext -> ext ))) {
222+ trie_remove (trie , leaf );
251223 }
252224
253- // Different case, but same value, e.g.
254- //
255- // *.tar.gz=01;31:*.TAR.GZ=01;31
256- if (esc_eq (iprev -> esc , ext -> esc -> seq , ext -> esc -> len )) {
257- return false;
225+ size_t len = ext -> len + 1 ;
226+ leaf = trie_insert_mem (trie , ext -> ext , len );
227+ if (!leaf ) {
228+ return -1 ;
258229 }
259230
260- // Different case, different value, e.g.
261- //
262- // *.tar.gz=01;31:*.TAR.GZ=01;33
263- return true;
231+ leaf -> value = ext ;
232+ return 0 ;
264233}
265234
266235/** Set the color for an extension. */
267- static int set_ext (struct colors * colors , char * key , char * value ) {
236+ static int set_ext (struct colors * colors , dchar * key , dchar * value ) {
268237 size_t len = dstrlen (key );
269238 struct ext_color * ext = varena_alloc (& colors -> ext_arena , len + 1 );
270239 if (!ext ) {
@@ -279,45 +248,19 @@ static int set_ext(struct colors *colors, char *key, char *value) {
279248 goto fail ;
280249 }
281250
282- key = memcpy (ext -> ext , key , len + 1 );
251+ memcpy (ext -> ext , key , len + 1 );
283252
284253 // Reverse the extension (`*.y.x` -> `x.y.*`) so we can use trie_find_prefix()
285- ext_reverse (key , len );
286-
287- // Find any pre-existing exact match
288- struct ext_color * prev = NULL ;
289- struct trie_leaf * leaf = trie_find_str (& colors -> ext_trie , key );
290- if (leaf ) {
291- prev = leaf -> value ;
292- trie_remove (& colors -> ext_trie , leaf );
293- }
294-
295- // A later *.x should override any earlier *.x, *.y.x, etc.
296- while ((leaf = trie_find_postfix (& colors -> ext_trie , key ))) {
297- trie_remove (& colors -> ext_trie , leaf );
298- }
254+ ext_reverse (ext -> ext , len );
299255
300256 // Insert the extension into the case-sensitive trie
301- leaf = trie_insert_str (& colors -> ext_trie , key );
302- if (!leaf ) {
303- goto fail ;
304- }
305- leaf -> value = ext ;
306-
307- // "Smart case": if the same extension is given with two different
308- // capitalizations (e.g. `*.y.x=31:*.Y.Z=32:`), make it case-sensitive
309- ext_tolower (key , len );
310- leaf = trie_insert_str (& colors -> iext_trie , key );
311- if (!leaf ) {
257+ if (insert_ext (& colors -> ext_trie , ext ) != 0 ) {
312258 goto fail ;
313259 }
314260
315- struct ext_color * iprev = leaf -> value ;
316- if (ext_case_sensitive (ext , prev , iprev )) {
317- iprev -> case_sensitive = true;
318- ext -> case_sensitive = true;
261+ if (colors -> ext_len < len ) {
262+ colors -> ext_len = len ;
319263 }
320- leaf -> value = ext ;
321264
322265 return 0 ;
323266
@@ -329,32 +272,83 @@ static int set_ext(struct colors *colors, char *key, char *value) {
329272 return -1 ;
330273}
331274
332- /** Rebuild the case-insensitive trie after all extensions have been parsed. */
333- static int build_iext_trie (struct colors * colors ) {
334- trie_clear (& colors -> iext_trie );
275+ /**
276+ * The "smart case" algorithm.
277+ *
278+ * @param ext
279+ * The current extension being added.
280+ * @param iext
281+ * The previous case-insensitive match, if any, for the same extension.
282+ * @return
283+ * Whether this extension should become case-sensitive.
284+ */
285+ static bool ext_case_sensitive (struct ext_color * ext , struct ext_color * iext ) {
286+ // This is the first case-insensitive occurrence of this extension, e.g.
287+ //
288+ // *.gz=01;31:*.tar.gz=01;33
289+ if (!iext ) {
290+ return false;
291+ }
335292
293+ // If the last version of this extension is already case-sensitive,
294+ // this one should be too, e.g.
295+ //
296+ // *.tar.gz=01;31:*.TAR.GZ=01;32:*.TAR.GZ=01;33
297+ if (iext -> case_sensitive ) {
298+ return true;
299+ }
300+
301+ // Different case, but same value, e.g.
302+ //
303+ // *.tar.gz=01;31:*.TAR.GZ=01;31
304+ if (esc_eq (iext -> esc , ext -> esc -> seq , ext -> esc -> len )) {
305+ return false;
306+ }
307+
308+ // Different case, different value, e.g.
309+ //
310+ // *.tar.gz=01;31:*.TAR.GZ=01;33
311+ return true;
312+ }
313+
314+ /** Build the case-insensitive trie, after all extensions have been parsed. */
315+ static int build_iext_trie (struct colors * colors ) {
316+ // Find which extensions should be case-sensitive
336317 for_trie (leaf , & colors -> ext_trie ) {
337- size_t len = leaf -> length - 1 ;
338- if (colors -> ext_len < len ) {
339- colors -> ext_len = len ;
318+ struct ext_color * ext = leaf -> value ;
319+
320+ // "Smart case": if the same extension is given with two different
321+ // capitalizations (e.g. `*.y.x=31:*.Y.Z=32:`), make it case-sensitive
322+ ext_tolower (ext -> ext , ext -> len );
323+
324+ size_t len = ext -> len + 1 ;
325+ struct trie_leaf * ileaf = trie_insert_mem (& colors -> iext_trie , ext -> ext , len );
326+ if (!ileaf ) {
327+ return -1 ;
340328 }
341329
330+ struct ext_color * iext = ileaf -> value ;
331+ if (ext_case_sensitive (ext , iext )) {
332+ ext -> case_sensitive = true;
333+ iext -> case_sensitive = true;
334+ }
335+
336+ ileaf -> value = ext ;
337+ }
338+
339+ // Rebuild the trie with only the case-insensitive ones
340+ trie_clear (& colors -> iext_trie );
341+
342+ for_trie (leaf , & colors -> ext_trie ) {
342343 struct ext_color * ext = leaf -> value ;
343344 if (ext -> case_sensitive ) {
344345 continue ;
345346 }
346347
347- // set_ext() already reversed and lowercased the extension
348- struct trie_leaf * ileaf ;
349- while ((ileaf = trie_find_postfix (& colors -> iext_trie , ext -> ext ))) {
350- trie_remove (& colors -> iext_trie , ileaf );
351- }
352-
353- ileaf = trie_insert_str (& colors -> iext_trie , ext -> ext );
354- if (!ileaf ) {
348+ // We already lowercased the extension above
349+ if (insert_ext (& colors -> iext_trie , ext ) != 0 ) {
355350 return -1 ;
356351 }
357- ileaf -> value = ext ;
358352 }
359353
360354 return 0 ;
0 commit comments