OSDN Git Service

branch: yandytex with kpathsea.
[putex/putex.git] / src / texsourc / kpathsea / kpathsea / str-list.c
1 /* str-list.c: define routines for string lists.
2
3     Copyright 1993, 2008, 2012 Karl Berry.
4     Copyright 2001, 2005 Olaf Weber.
5
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public License
17    along with this library; if not, see <http://www.gnu.org/licenses/>.  */
18
19 #include <kpathsea/config.h>
20
21 #include <kpathsea/str-list.h>
22
23
24 /* See the .h file for comments.  */
25
26
27 void
28 str_list_add (str_list_type *l,  string s)
29 {
30   STR_LIST_LENGTH (*l)++;
31   XRETALLOC (STR_LIST (*l), STR_LIST_LENGTH (*l), string);
32   STR_LIST_LAST_ELT (*l) = s;
33 }
34
35 void
36 cstr_list_add (cstr_list_type *l,  const_string s)
37 {
38   STR_LIST_LENGTH (*l)++;
39   XRETALLOC (STR_LIST (*l), STR_LIST_LENGTH (*l), const_string);
40   STR_LIST_LAST_ELT (*l) = s;
41 }
42
43
44 /* May as well save some reallocations and do everything in a chunk
45    instead of calling str_list_add on each element.  */
46
47 void
48 str_list_concat (str_list_type *target,  str_list_type more)
49 {
50   unsigned e;
51   unsigned prev_len = STR_LIST_LENGTH (*target);
52
53   STR_LIST_LENGTH (*target) += STR_LIST_LENGTH (more);
54   XRETALLOC (STR_LIST (*target), STR_LIST_LENGTH (*target), string);
55
56   for (e = 0; e < STR_LIST_LENGTH (more); e++)
57     STR_LIST_ELT (*target, prev_len + e) = STR_LIST_ELT (more, e);
58 }
59
60
61 /* Concatenate the elements of more to each element of target.  This
62    _must_ be done with the first index varying fastest. */
63 /* Note that we free the old elements of target as well. */
64
65 void
66 str_list_concat_elements (str_list_type *target,  str_list_type more)
67 {
68     if (STR_LIST_LENGTH(more) == 0) {
69         return;
70     } else if (STR_LIST_LENGTH(*target) == 0) {
71         unsigned int i;
72         STR_LIST_LENGTH(*target) = STR_LIST_LENGTH(more);
73         STR_LIST(*target) =
74                 (string*)xmalloc(STR_LIST_LENGTH(more)*sizeof(char*));
75         for (i=0;i!=STR_LIST_LENGTH(more);++i) {
76             STR_LIST_ELT(*target,i)=xstrdup(STR_LIST_ELT(more,i));
77         }
78         return;
79     } else {
80         unsigned new_len;
81         char ** new_list;
82         unsigned int i,j;
83         new_list = (string*)xmalloc(STR_LIST_LENGTH (*target)
84                                     * STR_LIST_LENGTH (more) * sizeof(char*));
85
86         new_len = 0;
87         for (j = 0; j != STR_LIST_LENGTH(more); ++j) {
88             for (i = 0; i != STR_LIST_LENGTH(*target); ++i) {
89                 new_list[new_len] = concat(STR_LIST_ELT(*target,i),
90                                            STR_LIST_ELT(more,j));
91                 ++new_len;
92             }
93         }
94         for (i = 0; i != STR_LIST_LENGTH(*target); ++i)
95             free(STR_LIST_ELT(*target, i));
96         free(STR_LIST(*target));
97         STR_LIST_LENGTH(*target) = new_len;
98         STR_LIST(*target) = new_list;
99     }
100 }
101
102
103 /* Free the list (but not the elements within it).  */
104
105 void
106 str_list_free (str_list_type *l)
107 {
108   if (STR_LIST (*l))
109     {
110       free (STR_LIST (*l));
111       STR_LIST (*l) = NULL;
112     }
113 }
114
115
116 \f
117 /* Remove duplicate elements from L, freeing their space.  Since our
118    lists are so short, we do a maximally inefficient bubble search.  */
119
120 void
121 str_list_uniqify (str_list_type *l)
122 {
123   unsigned e;
124   str_list_type ret = str_list_init ();
125
126   for (e = 0; e < STR_LIST_LENGTH (*l); e++) {
127     string elt1 = STR_LIST_ELT (*l, e);
128     unsigned f;
129     for (f = e + 1; f < STR_LIST_LENGTH (*l); f++) {
130       string elt2 = STR_LIST_ELT (*l, f);
131       /* I don't think our list should ever contain NULL's, but if
132          it does, let it stay and don't bother collapsing multiple
133          NULL's into one.  */
134       if (FILESTRCASEEQ (elt1, elt2)) {
135         break;
136       }
137     }
138
139     if (f == STR_LIST_LENGTH (*l)) {
140       str_list_add (&ret, elt1); /* not found */
141     } else {
142       free (elt1);  /* duplicate, forget this one */
143     }
144   }
145
146   /* Replace the passed list with what we constructed.  */
147   *l = ret;
148 }