1 /* libcomps - C alternative to yum.comps library
2  * Copyright (C) 2013 Jindrich Luza
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to  Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
17  * USA
18  */
19 
20 #include "comps_set.h"
21 #include <stdlib.h>
22 #include <string.h>
23 
comps_set_index_cmp(void * item1,void * item2)24 char comps_set_index_cmp(void *item1, void *item2) {
25     return *(unsigned int*)item1 == *(unsigned int*)item2;
26 }
comps_set_index_clone(void * item)27 void* comps_set_index_clone(void *item) {
28     void * ret;
29     if ((ret = malloc(sizeof(unsigned int))) == NULL)
30         return NULL;
31     memcpy(ret, item, sizeof(unsigned int));
32     return ret;
33 }
34 
comps_set_create()35 COMPS_Set * comps_set_create()
36 {
37     COMPS_Set *ret;
38     if ((ret = malloc(sizeof(COMPS_Set))) == NULL) {
39         return NULL;
40     }
41     ret->data = comps_hslist_create();
42     if (ret->data == NULL) {
43         free(ret);
44         return NULL;
45     }
46     return ret;
47 }
48 
comps_set_destroy(COMPS_Set ** set)49 void comps_set_destroy(COMPS_Set **set) {
50     comps_hslist_destroy(&(*set)->data);
51     free(*set);
52     *set = NULL;
53 }
54 
comps_set_destroy_v(void * set)55 inline void comps_set_destroy_v(void *set) {
56     comps_hslist_destroy(&((COMPS_Set*)set)->data);
57     free((COMPS_Set*)set);
58 }
59 
comps_set_init(COMPS_Set * set,void * (* data_constructor)(void *),void * (* data_cloner)(void *),void (* data_destructor)(void *),char (* eqf)(void *,void *))60 void comps_set_init(COMPS_Set * set, void* (*data_constructor)(void*),
61                                      void* (*data_cloner)(void*),
62                                      void (*data_destructor)(void*),
63                                      char (*eqf)(void*, void*)) {
64     if (set == NULL)
65         return;
66     set->data_constructor = data_constructor;
67     set->data_destructor = data_destructor;
68     set->data_cloner = data_cloner;
69     set->eqf = eqf;
70     comps_hslist_init(set->data, data_constructor, data_cloner, data_destructor);
71 }
72 
comps_set_in(COMPS_Set * set,void * item)73 char comps_set_in(COMPS_Set * set, void * item) {
74     COMPS_HSListItem * it;
75     for (it = set->data->first; it != NULL; it = it->next) {
76         if (set->eqf(it->data, item))
77             return 1;
78     }
79     return 0;
80 }
81 
comps_set_at(COMPS_Set * set,void * item)82 int comps_set_at(COMPS_Set * set, void * item) {
83     COMPS_HSListItem * it;
84     int x;
85     for (x=0, it = set->data->first; it != NULL; it = it->next, x++) {
86         if (set->eqf(it->data, item)) {
87             return x;
88         }
89     }
90     return -1;
91 }
92 
comps_set_data_at(COMPS_Set * set,void * item)93 void* comps_set_data_at(COMPS_Set * set, void * item) {
94     COMPS_HSListItem * it;
95     for (it = set->data->first; it != NULL; it = it->next) {
96         if (set->eqf(it->data, item)) {
97             return it->data;
98         }
99     }
100     return NULL;
101 }
102 
comps_set_add(COMPS_Set * set,void * item)103 char comps_set_add(COMPS_Set * set, void *item) {
104     COMPS_HSListItem * it;
105 
106     for (it = set->data->first; it != NULL; it = it->next) {
107         if (set->eqf(it->data, item)) {
108             return 0;
109         }
110     }
111     comps_hslist_append(set->data, item, 1);
112     return 1;
113 }
114 
comps_set_remove(COMPS_Set * set,void * item)115 void* comps_set_remove(COMPS_Set *set, void *item) {
116     void * ret;
117     COMPS_HSListItem * it;
118     for (it = set->data->first; it != NULL; it = it->next) {
119         if (set->eqf(it->data, item)) {
120             comps_hslist_remove(set->data, it);
121             ret = it->data;
122             free(it);
123             return ret;
124         }
125     }
126     return NULL;
127 }
128 
comps_set_is_empty(COMPS_Set * set)129 inline char comps_set_is_empty(COMPS_Set *set) {
130     if (set->data->first == NULL) {
131         return 1;
132     } else return 0;
133 }
134 
comps_set_cmp(COMPS_Set * set1,COMPS_Set * set2)135 char comps_set_cmp(COMPS_Set *set1, COMPS_Set *set2) {
136     unsigned int x, index;
137     COMPS_Set *not_processed1, *not_processed2;
138     COMPS_HSListItem *it;
139     void *item;//, *tmpdata;
140     char ret;
141     int at;
142 
143     not_processed1 = comps_set_create();
144     not_processed2 = comps_set_create();
145     comps_set_init(not_processed1, &comps_set_index_clone,
146                                    &comps_set_index_clone,
147                                    &free, &comps_set_index_cmp);
148     comps_set_init(not_processed2, &comps_set_index_clone,
149                                    &comps_set_index_clone,
150                                    &free, &comps_set_index_cmp);
151     for (x = 0, it = set1->data->first; it!= NULL; it = it->next, x++) {
152         comps_hslist_append(not_processed1->data, &x, 1);
153     }
154     for (x = 0, it = set2->data->first; it!= NULL; it = it->next, x++) {
155         comps_hslist_append(not_processed2->data, &x, 1);
156     }
157     it = set1->data->first;
158 
159     index = 0;
160     ret = 0;
161     while (!comps_set_is_empty(not_processed1) &&
162            !comps_set_is_empty(not_processed2)) {
163         if ((at = comps_set_at(set2, it->data)) != -1) {
164             item = comps_set_remove(not_processed1, (void*)&index);
165             free(item);
166             item = comps_set_remove(not_processed2 , (void*)&at);
167             free(item);
168             //tmpdata = comps_hslist_data_at(set2->data, at);
169         } else {
170             ret = 2;
171             break;
172         }
173         it = it->next;
174         index++;
175         if (it == NULL) break;
176     }
177     if (ret == 0) {
178         if (comps_set_is_empty(not_processed1)) {
179             /*if (comps_set_is_empty(not_processed2))
180                 ret = 0;*/
181             if (!comps_set_is_empty(not_processed2))
182                 ret = -1;
183         } else {
184             if (comps_set_is_empty(not_processed2))
185                 ret = 1;
186             else ret = 2;
187         }
188     }
189     comps_set_destroy(&not_processed1);
190     comps_set_destroy(&not_processed2);
191     return ret;
192 }
193 
comps_set_clear(COMPS_Set * set)194 inline void comps_set_clear(COMPS_Set *set) {
195     comps_hslist_clear(set->data);
196 }
197 
198