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_doc.h"
21 #include "comps_set.h"
22 //#include "comps_types.h"
23 #include "comps_utils.h"
24 #include "comps_default.h"
25
26 #include <stdio.h>
27 #include <assert.h>
28 static signed char comps_doc_xml(COMPS_Doc *doc, xmlTextWriterPtr writer,
29 COMPS_XMLOptions *xml_options,
30 COMPS_DefaultsOptions *def_options);
31
comps_doc_create(COMPS_Doc * doc,COMPS_Object ** args)32 void comps_doc_create(COMPS_Doc* doc, COMPS_Object **args) {
33 doc->objects = COMPS_OBJECT_CREATE(COMPS_ObjDict, NULL);
34 doc->log = COMPS_OBJECT_CREATE(COMPS_Log, NULL);
35 //doc->log = comps_log_create(0);
36 if (args && args[0]->obj_info == &COMPS_Str_ObjInfo) {
37 doc->encoding = (COMPS_Str*) comps_object_incref(args[0]);
38 } else {
39 doc->encoding = NULL;
40 }
41 doc->doctype_name = comps_str(comps_default_doctype_name);
42 doc->doctype_sysid = comps_str(comps_default_doctype_sysid);
43 doc->doctype_pubid = comps_str(comps_default_doctype_pubid);
44 doc->lang = NULL;
45 }
COMPS_CREATE_u(doc,COMPS_Doc)46 COMPS_CREATE_u(doc, COMPS_Doc)
47
48 void comps_doc_copy(COMPS_Doc *doc_dst, COMPS_Doc *doc_src) {
49 doc_dst->encoding = (COMPS_Str*) COMPS_OBJECT_COPY(doc_src->encoding);
50 doc_dst->doctype_name = (COMPS_Str*) COMPS_OBJECT_COPY(doc_src->doctype_name);
51 doc_dst->doctype_sysid = (COMPS_Str*) COMPS_OBJECT_COPY(doc_src->doctype_sysid);
52 doc_dst->doctype_pubid = (COMPS_Str*) COMPS_OBJECT_COPY(doc_src->doctype_pubid);
53 doc_dst->objects = (COMPS_ObjDict*) COMPS_OBJECT_COPY(doc_src->objects);
54 }
COMPS_COPY_u(doc,COMPS_Doc)55 COMPS_COPY_u(doc, COMPS_Doc)
56
57 void comps_doc_destroy(COMPS_Doc *doc) {
58 if (doc != NULL) {
59 COMPS_OBJECT_DESTROY(doc->log);
60 COMPS_OBJECT_DESTROY(doc->objects);
61 COMPS_OBJECT_DESTROY(doc->encoding);
62 COMPS_OBJECT_DESTROY(doc->doctype_name);
63 COMPS_OBJECT_DESTROY(doc->doctype_sysid);
64 COMPS_OBJECT_DESTROY(doc->doctype_pubid);
65 }
66 }
COMPS_DESTROY_u(doc,COMPS_Doc)67 COMPS_DESTROY_u(doc, COMPS_Doc)
68
69 signed char comps_doc_cmp_u(COMPS_Object *obj1, COMPS_Object *obj2) {
70 COMPS_Object *tmp1, *tmp2;
71 signed char ret;
72
73 #define _doc1_ ((COMPS_Doc*)obj1)
74 #define _doc2_ ((COMPS_Doc*)obj2)
75
76 if (!COMPS_OBJECT_CMP(_doc1_->encoding, _doc2_->encoding)) {
77 return 0;
78 }
79 if (!COMPS_OBJECT_CMP(_doc1_->doctype_name, _doc2_->doctype_name)) {
80 return 0;
81 }
82 if (!COMPS_OBJECT_CMP(_doc1_->doctype_sysid, _doc2_->doctype_sysid)) {
83 return 0;
84 }
85 if (!COMPS_OBJECT_CMP(_doc1_->doctype_pubid, _doc2_->doctype_pubid)) {
86 return 0;
87 }
88 tmp1 = (COMPS_Object*) comps_doc_categories(_doc1_);
89 tmp2 = (COMPS_Object*) comps_doc_categories(_doc2_);
90 ret = comps_object_cmp(tmp1, tmp2);
91 COMPS_OBJECT_DESTROY(tmp1);
92 COMPS_OBJECT_DESTROY(tmp2);
93 if (!ret) {
94 //printf("categories cmp fail\n");
95 return ret;
96 }
97
98 tmp1 = (COMPS_Object*) comps_doc_groups(_doc1_);
99 tmp2 = (COMPS_Object*) comps_doc_groups(_doc2_);
100 ret = comps_object_cmp(tmp1, tmp2);
101 COMPS_OBJECT_DESTROY(tmp1);
102 COMPS_OBJECT_DESTROY(tmp2);
103 if (!ret) {
104 //printf("groups cmp fail\n");
105 return ret;
106 }
107
108 tmp1 = (COMPS_Object*) comps_doc_environments(_doc1_);
109 tmp2 = (COMPS_Object*) comps_doc_environments(_doc2_);
110 ret = comps_object_cmp(tmp1, tmp2);
111 COMPS_OBJECT_DESTROY(tmp1);
112 COMPS_OBJECT_DESTROY(tmp2);
113 if (!ret) {
114 return ret;
115 }
116
117 tmp1 = (COMPS_Object*) comps_doc_langpacks(_doc1_);
118 tmp2 = (COMPS_Object*) comps_doc_langpacks(_doc2_);
119 ret = comps_object_cmp(tmp1, tmp2);
120 COMPS_OBJECT_DESTROY(tmp1);
121 COMPS_OBJECT_DESTROY(tmp2);
122 if (!ret) {
123 return ret;
124 }
125
126 tmp1 = (COMPS_Object*) comps_doc_blacklist(_doc1_);
127 tmp2 = (COMPS_Object*) comps_doc_blacklist(_doc2_);
128 ret = comps_object_cmp(tmp1, tmp2);
129 COMPS_OBJECT_DESTROY(tmp1);
130 COMPS_OBJECT_DESTROY(tmp2);
131 if (!ret) {
132 //printf("blacklist cmp fail\n");
133 return ret;
134 }
135
136 tmp1 = (COMPS_Object*) comps_doc_whiteout(_doc1_);
137 tmp2 = (COMPS_Object*) comps_doc_whiteout(_doc2_);
138 ret = comps_object_cmp(tmp1, tmp2);
139 COMPS_OBJECT_DESTROY(tmp1);
140 COMPS_OBJECT_DESTROY(tmp2);
141 if (!ret) {
142 //printf("whiteout cmp fail\n");
143 return ret;
144 }
145
146 return ret;
147 }
148
comps_doc_clear(COMPS_Doc * doc)149 inline void comps_doc_clear(COMPS_Doc *doc) {
150 if (doc == NULL) return;
151 //comps_objdict_clear(doc->objects);
152 }
153
154 COMPS_DOC_GETOBJLIST(groups) /*comps_doc.h macro*/
COMPS_DOC_SETOBJLIST(groups)155 COMPS_DOC_SETOBJLIST(groups) /*comps_doc.h macro*/
156 COMPS_DOC_ADDOBJLIST(groups, group, COMPS_DocGroup) /*comps_doc.h macro*/
157 COMPS_DOC_GETOBJLIST(categories) /*comps_doc.h macro*/
158 COMPS_DOC_SETOBJLIST(categories) /*comps_doc.h macro*/
159 COMPS_DOC_ADDOBJLIST(categories, category, COMPS_DocCategory) /*comps_doc.h macro*/
160 COMPS_DOC_GETOBJLIST(environments) /*comps_doc.h macro*/
161 COMPS_DOC_SETOBJLIST(environments) /*comps_doc.h macro*/
162 COMPS_DOC_ADDOBJLIST(environments, environment, COMPS_DocEnv) /*comps_doc.h macro*/
163 COMPS_DOC_GETOBJDICT(langpacks) /*comps_doc.h macro*/
164 COMPS_DOC_SETOBJDICT(langpacks) /*comps_doc.h macro*/
165 COMPS_DOC_ADDOBJDICT(langpacks, langpack) /*comps_doc.h macro*/
166 COMPS_DOC_GETOBJMDICT(blacklist) /*comps_doc.h macro*/
167 COMPS_DOC_SETOBJMDICT(blacklist) /*comps_doc.h macro*/
168 COMPS_DOC_ADDOBJMDICT(blacklist, blacklist) /*comps_doc.h macro*/
169 COMPS_DOC_GETOBJMDICT(whiteout) /*comps_doc.h macro*/
170 COMPS_DOC_SETOBJMDICT(whiteout) /*comps_doc.h macro*/
171 COMPS_DOC_ADDOBJMDICT(whiteout, whiteout) /*comps_doc.h macro*/
172
173 COMPS_DOC_SETPROP(lang, COMPS_Str) /*comps_doc.h macro*/
174
175
176 signed char comps2xml_f(COMPS_Doc * doc, char *filename, char stdoutredirect,
177 COMPS_XMLOptions *xml_options,
178 COMPS_DefaultsOptions *def_options) {
179 xmlDocPtr xmldoc;
180 int retc;
181 char *str;
182 signed char genret;
183
184 doc->log->std_out = stdoutredirect;
185 xmlTextWriterPtr writer = xmlNewTextWriterDoc(&xmldoc, 0);
186
187 if ((COMPS_Object*)doc->encoding) {
188 str = comps_object_tostr((COMPS_Object*)doc->encoding);
189 retc = xmlTextWriterStartDocument(writer, NULL, str, NULL);
190 free(str);
191 } else {
192 retc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
193 }
194 if (retc<0)
195 comps_log_error(doc->log, COMPS_ERR_XMLGEN, 0);
196
197 if (!xml_options)
198 xml_options = &COMPS_XMLDefaultOptions;
199 if (!def_options)
200 def_options = &COMPS_DDefaultsOptions;
201 genret = comps_doc_xml(doc, writer, xml_options, def_options);
202 retc = xmlTextWriterEndDocument(writer);
203 if (retc<0)
204 comps_log_error(doc->log, COMPS_ERR_XMLGEN, 0);
205
206 retc = xmlSaveFormatFileEnc(filename, xmldoc, NULL, 1);
207 if (retc<0)
208 comps_log_error_x(doc->log, COMPS_ERR_WRITEF,
209 1, comps_str(filename));
210
211 xmlFreeTextWriter(writer);
212 xmlFreeDoc(xmldoc);
213 xmlCleanupParser();
214 xmlMemoryDump();
215 return genret;
216 }
217
comps2xml_str(COMPS_Doc * doc,COMPS_XMLOptions * xml_options,COMPS_DefaultsOptions * def_options)218 char* comps2xml_str(COMPS_Doc *doc, COMPS_XMLOptions *xml_options,
219 COMPS_DefaultsOptions *def_options) {
220 xmlDocPtr xmldoc;
221 const char *xmlstr;
222 signed char genret;
223 char *str, *ret;
224 int retc;
225
226 xmlBuffer *xmlbuff = xmlBufferCreate();
227 xmlOutputBuffer *xmlobuff = xmlOutputBufferCreateBuffer(xmlbuff, 0);
228 xmlTextWriterPtr writer = xmlNewTextWriterDoc(&xmldoc, 0);
229
230 if ((COMPS_Object*)doc->encoding) {
231 str = comps_object_tostr((COMPS_Object*)doc->encoding);
232 retc = xmlTextWriterStartDocument(writer, NULL, str, NULL);
233 free(str);
234 } else {
235 retc = xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL);
236 }
237 if (retc<0) comps_log_error(doc->log, COMPS_ERR_XMLGEN, 0);
238
239 if (!xml_options)
240 xml_options = &COMPS_XMLDefaultOptions;
241 if (!def_options)
242 def_options = &COMPS_DDefaultsOptions;
243 genret = comps_doc_xml(doc, writer, xml_options, def_options);
244 if (genret)
245 comps_log_error(doc->log, COMPS_ERR_XMLGEN, 0);
246 if (retc<0)
247 comps_log_error(doc->log, COMPS_ERR_XMLGEN, 0);
248 retc = xmlTextWriterEndDocument(writer);
249 if (retc<0) comps_log_error(doc->log, COMPS_ERR_XMLGEN, 0);
250 xmlSaveFormatFileTo(xmlobuff, xmldoc, NULL, 1);
251
252 xmlFreeTextWriter(writer);
253 xmlFreeDoc(xmldoc);
254
255 xmlstr =(char*) xmlBufferContent(xmlbuff);
256 ret = malloc(sizeof(char) * (strlen(xmlstr)+1));
257 if (ret == NULL) {
258 xmlBufferFree(xmlbuff);
259 xmlCleanupParser();
260 xmlMemoryDump();
261 return NULL;
262 } else {
263 memcpy(ret, xmlstr, sizeof(char)*(strlen(xmlstr)+1));
264 }
265 xmlBufferFree(xmlbuff);
266
267 xmlCleanupParser();
268 xmlMemoryDump();
269 return ret;
270 }
271
comps_doc_union(COMPS_Doc * c1,COMPS_Doc * c2)272 COMPS_Doc* comps_doc_union(COMPS_Doc *c1, COMPS_Doc *c2) {
273 COMPS_ObjListIt *it;
274 COMPS_Set *set;
275 COMPS_Doc *res;
276 COMPS_DocGroup *tmpgroup;
277 COMPS_DocCategory *tmpcat;
278 COMPS_DocEnv *tmpenv;
279 COMPS_HSListItem *hsit;
280 COMPS_ObjList *groups = comps_doc_groups(c1);
281 COMPS_ObjList *categories = comps_doc_categories(c1);
282 COMPS_ObjList *envs = comps_doc_environments(c1);
283 COMPS_ObjDict *langpacks, *d1, *d2;
284
285 void *tmpdata;
286 res = COMPS_OBJECT_CREATE(COMPS_Doc, (COMPS_Object*[]){(COMPS_Object*)
287 c1->encoding});
288
289 set = comps_set_create();
290 comps_set_init(set, NULL, NULL, NULL, &__comps_docgroup_idcmp);
291
292 for (it = groups ? groups->first : NULL; it != NULL; it = it->next) {
293 comps_set_add(set, comps_object_copy(it->comps_obj));
294 }
295 COMPS_OBJECT_DESTROY(groups);
296 groups = comps_doc_groups(c2);
297 for (it = groups ? groups->first : NULL; it != NULL; it = it->next) {
298 if (comps_set_in(set, it->comps_obj)) {
299 tmpgroup = comps_docgroup_union(
300 (COMPS_DocGroup*)comps_set_data_at(set,
301 it->comps_obj),
302 (COMPS_DocGroup*)it->comps_obj);
303 tmpdata = comps_set_data_at(set, it->comps_obj);
304 comps_set_remove(set, it->comps_obj);
305 COMPS_OBJECT_DESTROY(tmpdata);
306 comps_set_add(set, tmpgroup);
307 } else {
308 comps_set_add(set, comps_object_copy(it->comps_obj));
309 }
310 }
311 COMPS_OBJECT_DESTROY(groups);
312 for (hsit = set->data->first; hsit != NULL; hsit = hsit->next) {
313 comps_doc_add_group(res, hsit->data);
314 }
315 comps_set_clear(set);
316
317 comps_set_init(set, NULL, NULL, NULL, &__comps_doccategory_idcmp);
318 for (it = categories ? categories->first : NULL; it != NULL; it = it->next) {
319 comps_set_add(set, comps_object_copy(it->comps_obj));
320 }
321 COMPS_OBJECT_DESTROY(categories);
322 categories = comps_doc_categories(c2);
323 for (it = categories ? categories->first : NULL; it != NULL; it = it->next) {
324 if (comps_set_in(set, it->comps_obj)) {
325 tmpcat = comps_doccategory_union(
326 (COMPS_DocCategory*)comps_set_data_at(set,
327 it->comps_obj),
328 (COMPS_DocCategory*)it->comps_obj);
329 tmpdata = comps_set_data_at(set, it->comps_obj);
330 comps_set_remove(set, it->comps_obj);
331 COMPS_OBJECT_DESTROY(tmpdata);
332 comps_set_add(set, tmpcat);
333 } else {
334 comps_set_add(set, comps_object_copy(it->comps_obj));
335 }
336 }
337 COMPS_OBJECT_DESTROY(categories);
338 for (hsit = set->data->first; hsit != NULL; hsit = hsit->next) {
339 comps_doc_add_category(res, hsit->data);
340 }
341 comps_set_clear(set);
342
343 comps_set_init(set, NULL, NULL, NULL, &__comps_docenv_idcmp);
344 if (envs) {
345 for (it = envs->first; it != NULL; it = it->next) {
346 comps_set_add(set, comps_object_copy(it->comps_obj));
347 }
348 }
349 COMPS_OBJECT_DESTROY(envs);
350 envs = comps_doc_environments(c2);
351 if (envs) {
352 for (it = envs->first; it != NULL; it = it->next) {
353 if (comps_set_in(set, it->comps_obj)) {
354 tmpenv = comps_docenv_union(
355 (COMPS_DocEnv*)comps_set_data_at(set,
356 it->comps_obj),
357 (COMPS_DocEnv*)it->comps_obj);
358 tmpdata = comps_set_data_at(set, it->comps_obj);
359 comps_set_remove(set, it->comps_obj);
360 comps_object_destroy((COMPS_Object*)tmpdata);
361 comps_set_add(set, tmpenv);
362 } else {
363 comps_set_add(set, comps_object_copy(it->comps_obj));
364 }
365 }
366 }
367 COMPS_OBJECT_DESTROY(envs);
368 for (hsit = set->data->first; hsit != NULL; hsit = hsit->next) {
369 comps_doc_add_environment(res, hsit->data);
370 }
371 comps_set_destroy(&set);
372
373 d1 = comps_doc_langpacks(c1);
374 d2 = comps_doc_langpacks(c2);
375 langpacks = comps_objdict_union(d1,d2);
376 COMPS_OBJECT_DESTROY(d1);
377 COMPS_OBJECT_DESTROY(d2);
378 comps_doc_set_langpacks(res, langpacks);
379 COMPS_OBJECT_DESTROY(langpacks);
380 return res;
381 }
382
383 /**
384 * Make intersection of two existing COMPS_Doc objects. Result intersection is
385 * completly new COMPS_Doc object (deep copy of those two).
386 * Intersection is made by objects ids. Objects of intersection is created
387 * by intersecting specific objects.
388 * @see comps_docgroup_intersect
389 * @see comps_doccategory_intersect
390 * @see comps_docenv_intersect
391 * @param c1 COMPS_Doc object
392 * @param c2 COMPS_Doc object
393 * @return new COMPS_Doc object
394 */
comps_doc_intersect(COMPS_Doc * c1,COMPS_Doc * c2)395 COMPS_Doc* comps_doc_intersect(COMPS_Doc *c1, COMPS_Doc *c2) {
396 COMPS_ObjListIt *it;
397 COMPS_Set *set;
398 COMPS_Doc *res;
399 COMPS_DocGroup *tmpgroup;
400 COMPS_DocCategory *tmpcat;
401 COMPS_DocEnv *tmpenv;
402 COMPS_ObjList *groups = comps_doc_groups(c1);
403 COMPS_ObjList *categories = comps_doc_categories(c1);
404 COMPS_ObjList *envs = comps_doc_environments(c1);
405
406 res = COMPS_OBJECT_CREATE(COMPS_Doc, (COMPS_Object*[])
407 {(COMPS_Object*)c1->encoding});
408
409 set = comps_set_create();
410 comps_set_init(set, NULL, NULL, NULL, &__comps_docgroup_idcmp);
411
412 for (it = groups->first; it != NULL; it = it->next) {
413 comps_set_add(set, it->comps_obj);
414 }
415 COMPS_OBJECT_DESTROY(groups);
416 groups = comps_doc_groups(c2);
417 for (it = groups->first; it != NULL; it = it->next) {
418 if (comps_set_in(set, it->comps_obj)) {
419 tmpgroup = comps_docgroup_intersect(
420 (COMPS_DocGroup*)it->comps_obj,
421 (COMPS_DocGroup*)comps_set_data_at(set,
422 it->comps_obj));
423 comps_doc_add_group(res, tmpgroup);
424 }
425 }
426 comps_set_clear(set);
427
428 comps_set_init(set, NULL, NULL, NULL, &__comps_doccategory_idcmp);
429 for (it = categories->first; it != NULL; it = it->next) {
430 comps_set_add(set, it->comps_obj);
431 }
432 COMPS_OBJECT_DESTROY(categories);
433 categories = comps_doc_categories(c2);
434 for (it = categories->first; it != NULL; it = it->next) {
435 if (comps_set_in(set, it->comps_obj)) {
436 tmpcat = comps_doccategory_intersect(
437 (COMPS_DocCategory*)it->comps_obj,
438 (COMPS_DocCategory*)comps_set_data_at(set,
439 it->comps_obj));
440 comps_doc_add_category(res, tmpcat);
441 }
442 }
443 comps_set_clear(set);
444
445 comps_set_init(set, NULL, NULL, NULL, &__comps_docenv_idcmp);
446 for (it = envs->first; it != NULL; it = it->next) {
447 comps_set_add(set, it->comps_obj);
448 }
449 COMPS_OBJECT_DESTROY(envs);
450 envs = comps_doc_environments(c2);
451 for (it = envs->first; it != NULL; it = it->next) {
452 if (comps_set_in(set, it->comps_obj)) {
453 tmpenv = comps_docenv_intersect(
454 (COMPS_DocEnv*)it->comps_obj,
455 (COMPS_DocEnv*)comps_set_data_at(set,it->comps_obj));
456 comps_doc_add_environment(res, tmpenv);
457 }
458 }
459 comps_set_destroy(&set);
460 COMPS_OBJECT_DESTROY(groups);
461 COMPS_OBJECT_DESTROY(categories);
462 COMPS_OBJECT_DESTROY(envs);
463
464 return res;
465 }
466
comps_doc_get_groups(COMPS_Doc * doc,char * id,char * name,char * desc,char * lang,int flags)467 COMPS_ObjList* comps_doc_get_groups(COMPS_Doc *doc, char *id, char *name,
468 char *desc, char *lang, int flags) {
469 COMPS_ObjListIt *it;
470 COMPS_ObjList *ret;
471 unsigned int matched, matched_max;
472 matched_max = 0;
473 COMPS_ObjList *groups = comps_doc_groups(doc);
474 COMPS_Str *objid, *objname, *objdesc, *tmp_prop;
475 objid = comps_str(id);
476 objname = comps_str(name);
477 objdesc = comps_str(desc);
478
479 ret = COMPS_OBJECT_CREATE(COMPS_ObjList, NULL);
480 #define group ((COMPS_DocGroup*)it->comps_obj)
481
482 if (id != NULL) matched_max++;
483 if (name != NULL) matched_max++;
484 if (desc != NULL) matched_max++;
485
486 for (it = (groups)?groups->first:NULL; it != NULL; it = it->next) {
487 matched = 0;
488 tmp_prop = (COMPS_Str*)comps_docgroup_get_id(group);
489 if (id && tmp_prop && comps_str_fnmatch(tmp_prop, id, flags)) {
490 matched++;
491 }
492 COMPS_OBJECT_DESTROY(tmp_prop);
493 tmp_prop = (COMPS_Str*)comps_docgroup_get_name(group);
494 if (name && !lang && tmp_prop && comps_str_fnmatch(tmp_prop, name, flags))
495 matched++;
496 else if (name && lang != NULL) {
497 COMPS_OBJECT_DESTROY(tmp_prop);
498 tmp_prop = (COMPS_Str*)comps_objdict_get(group->name_by_lang, lang);
499 //printf("tmp_prop %s\n", tmp_prop->val);
500 if (tmp_prop && comps_str_fnmatch(tmp_prop, name, flags)) matched++;
501 }
502 COMPS_OBJECT_DESTROY(tmp_prop);
503 tmp_prop = (COMPS_Str*)comps_docgroup_get_desc(group);
504 if (desc && tmp_prop && comps_str_fnmatch(tmp_prop, desc, flags) == 1)
505 matched++;
506 else if (desc && lang != NULL) {
507 COMPS_OBJECT_DESTROY(tmp_prop);
508 tmp_prop = (COMPS_Str*)comps_objdict_get(group->desc_by_lang, lang);
509 if (tmp_prop && comps_str_fnmatch(tmp_prop, desc, flags)) matched++;
510 }
511 if (matched == matched_max) {
512 comps_objlist_append(ret, (COMPS_Object*)group);
513 }
514 COMPS_OBJECT_DESTROY(tmp_prop);
515 }
516 COMPS_OBJECT_DESTROY(objid);
517 COMPS_OBJECT_DESTROY(objname);
518 COMPS_OBJECT_DESTROY(objdesc);
519 COMPS_OBJECT_DESTROY(groups);
520 return ret;
521 #undef group
522 }
523
comps_doc_get_categories(COMPS_Doc * doc,char * id,char * name,char * desc,char * lang,int flags)524 COMPS_ObjList* comps_doc_get_categories(COMPS_Doc *doc, char *id, char *name,
525 char *desc, char *lang, int flags) {
526 COMPS_ObjListIt *it;
527 COMPS_ObjList *ret;
528 unsigned int matched, matched_max;
529 matched_max = 0;
530 COMPS_ObjList *categories = comps_doc_categories(doc);
531 //COMPS_Object *tmp_prop;
532 COMPS_Str *objid, *objname, *objdesc, *tmp_prop;
533 objid = comps_str(id);
534 objname = comps_str(name);
535 objdesc = comps_str(desc);
536
537 ret = COMPS_OBJECT_CREATE(COMPS_ObjList, NULL);
538 #define category ((COMPS_DocCategory*)it->comps_obj)
539
540 if (id != NULL) matched_max++;
541 if (name != NULL) matched_max++;
542 if (desc != NULL) matched_max++;
543
544 for (it = (categories)?categories->first:NULL; it != NULL; it = it->next) {
545 matched = 0;
546 tmp_prop = (COMPS_Str*)comps_doccategory_get_id(category);
547 if (id && tmp_prop && comps_str_fnmatch(tmp_prop, id, flags)) {
548 matched++;
549 }
550 COMPS_OBJECT_DESTROY(tmp_prop);
551 tmp_prop = (COMPS_Str*)comps_doccategory_get_name(category);
552 if (name && !lang && tmp_prop && comps_str_fnmatch(tmp_prop, name, flags))
553 matched++;
554 else if (name && lang != NULL) {
555 COMPS_OBJECT_DESTROY(tmp_prop);
556 tmp_prop = (COMPS_Str*)comps_objdict_get(category->name_by_lang, lang);
557 if (tmp_prop && comps_str_fnmatch(tmp_prop, name, flags)) matched++;
558 }
559 COMPS_OBJECT_DESTROY(tmp_prop);
560 tmp_prop = (COMPS_Str*)comps_doccategory_get_desc(category);
561 if (desc && !lang && tmp_prop && comps_str_fnmatch(tmp_prop, desc, flags))
562 matched++;
563 else if (desc && lang != NULL) {
564 COMPS_OBJECT_DESTROY(tmp_prop);
565 tmp_prop = (COMPS_Str*)comps_objdict_get(category->desc_by_lang, lang);
566 if (tmp_prop && comps_str_fnmatch(tmp_prop, desc, flags)) matched++;
567 }
568 if (matched == matched_max) {
569 comps_objlist_append(ret, (COMPS_Object*)category);
570 }
571 COMPS_OBJECT_DESTROY(tmp_prop);
572 }
573 COMPS_OBJECT_DESTROY(objid);
574 COMPS_OBJECT_DESTROY(objname);
575 COMPS_OBJECT_DESTROY(objdesc);
576 COMPS_OBJECT_DESTROY(categories);
577 return ret;
578 #undef category
579 }
580
comps_doc_get_envs(COMPS_Doc * doc,char * id,char * name,char * desc,char * lang,int flags)581 COMPS_ObjList* comps_doc_get_envs(COMPS_Doc *doc, char *id, char *name,
582 char *desc, char *lang, int flags) {
583 COMPS_ObjListIt *it;
584 COMPS_ObjList *ret;
585 unsigned int matched, matched_max;
586 matched_max = 0;
587 COMPS_ObjList *envs = comps_doc_environments(doc);
588 //COMPS_Object *tmp_prop;
589 COMPS_Str *objid, *objname, *objdesc, *tmp_prop;
590 objid = comps_str(id);
591 objname = comps_str(name);
592 objdesc = comps_str(desc);
593
594 ret = COMPS_OBJECT_CREATE(COMPS_ObjList, NULL);
595 #define env ((COMPS_DocEnv*)it->comps_obj)
596
597 if (id != NULL) matched_max++;
598 if (name != NULL) matched_max++;
599 if (desc != NULL) matched_max++;
600
601 for (it = (envs)?envs->first:NULL; it != NULL; it = it->next) {
602 matched = 0;
603 tmp_prop = (COMPS_Str*)comps_docenv_get_id(env);
604 if (id && tmp_prop && comps_str_fnmatch(tmp_prop, id, flags)) {
605 matched++;
606 }
607 COMPS_OBJECT_DESTROY(tmp_prop);
608 tmp_prop = (COMPS_Str*)comps_docenv_get_name(env);
609 if (name && !lang && tmp_prop && comps_str_fnmatch(tmp_prop, name, flags))
610 matched++;
611 else if (name && lang != NULL) {
612 COMPS_OBJECT_DESTROY(tmp_prop);
613 tmp_prop = (COMPS_Str*)comps_objdict_get(env->name_by_lang, lang);
614 if (tmp_prop && comps_str_fnmatch(tmp_prop, name, flags)) matched++;
615 }
616 COMPS_OBJECT_DESTROY(tmp_prop);
617 tmp_prop = (COMPS_Str*)comps_docenv_get_desc(env);
618 if (desc && !lang && tmp_prop && comps_str_fnmatch(tmp_prop, desc, flags))
619 matched++;
620 else if (desc && lang != NULL) {
621 COMPS_OBJECT_DESTROY(tmp_prop);
622 tmp_prop = (COMPS_Str*)comps_objdict_get(env->desc_by_lang, lang);
623 if (tmp_prop && comps_str_fnmatch(tmp_prop, desc, flags)) matched++;
624 }
625 if (matched == matched_max) {
626 comps_objlist_append(ret, (COMPS_Object*)env);
627 }
628 COMPS_OBJECT_DESTROY(tmp_prop);
629 }
630 COMPS_OBJECT_DESTROY(objid);
631 COMPS_OBJECT_DESTROY(objname);
632 COMPS_OBJECT_DESTROY(objdesc);
633 COMPS_OBJECT_DESTROY(envs);
634 return ret;
635 #undef env
636 }
637
comps_doc_xml(COMPS_Doc * doc,xmlTextWriterPtr writer,COMPS_XMLOptions * xml_options,COMPS_DefaultsOptions * def_options)638 static signed char comps_doc_xml(COMPS_Doc *doc, xmlTextWriterPtr writer,
639 COMPS_XMLOptions *xml_options,
640 COMPS_DefaultsOptions *def_options) {
641 COMPS_ObjListIt *it;
642 COMPS_ObjList *list;
643 COMPS_ObjDict *dict;
644 COMPS_ObjMDict *mdict;
645 COMPS_HSList *hslist;
646 COMPS_HSListItem *hsit;
647 char *tmp;
648 int retc;
649 signed char ret = 0, tmpret;
650
651 retc = xmlTextWriterStartDTD(writer, (const xmlChar*)doc->doctype_name->val,
652 (const xmlChar*)doc->doctype_pubid->val,
653 (const xmlChar*)doc->doctype_sysid->val);
654 xmlTextWriterEndDTD(writer);
655 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) return -1;
656
657 retc = xmlTextWriterStartElement(writer, BAD_CAST "comps");
658 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) return -1;
659 list = comps_doc_groups(doc);
660 if (list) {
661 for (it = list->first; it != NULL; it = it->next) {
662 tmpret = comps_docgroup_xml((COMPS_DocGroup*)it->comps_obj,
663 writer, doc->log, xml_options,
664 def_options);
665 if (tmpret == -1) return -1;
666 else ret += tmpret;
667 }
668 }
669 COMPS_OBJECT_DESTROY(list);
670 list = comps_doc_categories(doc);
671 if (list) {
672 for (it = list->first; it != NULL; it = it->next) {
673 tmpret = comps_doccategory_xml((COMPS_DocCategory*)it->comps_obj,
674 writer, doc->log, xml_options,
675 def_options);
676 if (tmpret == -1) return -1;
677 else ret += tmpret;
678 }
679 }
680 COMPS_OBJECT_DESTROY(list);
681 list = comps_doc_environments(doc);
682 if (list) {
683 for (it = list->first; it != NULL; it = it->next) {
684 tmpret = comps_docenv_xml((COMPS_DocEnv*)it->comps_obj,
685 writer, doc->log, xml_options,
686 def_options);
687 if (tmpret == -1) return -1;
688 else ret += tmpret;
689 }
690 }
691 COMPS_OBJECT_DESTROY(list);
692 dict = comps_doc_langpacks(doc);
693 if (dict && dict->len) {
694 retc = xmlTextWriterStartElement(writer, BAD_CAST "langpacks");
695 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
696 COMPS_OBJECT_DESTROY(dict);
697 return -1;
698 }
699 hslist = comps_objrtree_pairs(dict);
700
701 for (hsit = hslist->first; hsit != NULL; hsit = hsit->next) {
702 retc = xmlTextWriterStartElement(writer, BAD_CAST "match");
703 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
704 COMPS_OBJECT_DESTROY(dict);
705 comps_hslist_destroy(&hslist);
706 return -1;
707 }
708
709 xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
710 (xmlChar*) ((COMPS_ObjRTreePair*)hsit->data)->key);
711
712 tmp = comps_object_tostr(((COMPS_ObjRTreePair*)hsit->data)->data);
713 xmlTextWriterWriteAttribute(writer, BAD_CAST "install", BAD_CAST tmp);
714 free(tmp);
715
716 retc = xmlTextWriterEndElement(writer);
717 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
718 COMPS_OBJECT_DESTROY(dict);
719 comps_hslist_destroy(&hslist);
720 return -1;
721 }
722 }
723 comps_hslist_destroy(&hslist);
724
725 retc = xmlTextWriterEndElement(writer);
726 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
727 COMPS_OBJECT_DESTROY(dict);
728 return -1;
729 }
730 }
731 COMPS_OBJECT_DESTROY(dict);
732
733 mdict = comps_doc_blacklist(doc);
734 if (mdict && mdict->len) {
735 retc = xmlTextWriterStartElement(writer, BAD_CAST "blacklist");
736 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
737 return -1;
738 }
739 hslist = comps_objmrtree_pairs(mdict);
740
741 for (hsit = hslist->first; hsit != NULL; hsit = hsit->next) {
742 for (it = ((COMPS_ObjMRTreePair*)hsit->data)->data->first;
743 it != NULL; it = it->next) {
744 retc = xmlTextWriterStartElement(writer, BAD_CAST "package");
745 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
746 comps_hslist_destroy(&hslist);
747 return -1;
748 }
749 xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
750 (xmlChar*) ((COMPS_ObjRTreePair*)hsit->data)->key);
751
752 tmp = comps_object_tostr(it->comps_obj);
753 xmlTextWriterWriteAttribute(writer, BAD_CAST "arch", BAD_CAST tmp);
754 free(tmp);
755
756 retc = xmlTextWriterEndElement(writer);
757 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
758 comps_hslist_destroy(&hslist);
759 return -1;
760 }
761 }
762 }
763 comps_hslist_destroy(&hslist);
764
765 retc = xmlTextWriterEndElement(writer);
766 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
767 return -1;
768 }
769 }
770 COMPS_OBJECT_DESTROY(mdict);
771 mdict = comps_doc_whiteout(doc);
772 if (mdict && mdict->len) {
773 retc = xmlTextWriterStartElement(writer, BAD_CAST "whiteout");
774 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
775 COMPS_OBJECT_DESTROY(mdict);
776 return -1;
777 }
778 hslist = comps_objmrtree_pairs(mdict);
779
780 for (hsit = hslist->first; hsit != NULL; hsit = hsit->next) {
781 for (it = ((COMPS_ObjMRTreePair*)hsit->data)->data->first;
782 it != NULL; it = it->next) {
783 retc = xmlTextWriterStartElement(writer, BAD_CAST "ignoredep");
784 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
785 comps_hslist_destroy(&hslist);
786 return -1;
787 }
788
789 xmlTextWriterWriteAttribute(writer, BAD_CAST "requires",
790 (xmlChar*) ((COMPS_ObjRTreePair*)hsit->data)->key);
791
792 tmp = comps_object_tostr(it->comps_obj);
793 xmlTextWriterWriteAttribute(writer, BAD_CAST "package", BAD_CAST tmp);
794 free(tmp);
795
796 retc = xmlTextWriterEndElement(writer);
797 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
798 comps_hslist_destroy(&hslist);
799 return -1;
800 }
801 }
802 }
803 comps_hslist_destroy(&hslist);
804
805 retc = xmlTextWriterEndElement(writer);
806 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) {
807 return -1;
808 }
809 }
810 COMPS_OBJECT_DESTROY(mdict);
811 retc = xmlTextWriterEndElement(writer);
812 if (__comps_check_xml_get(retc, (COMPS_Object*)doc->log) < 0) return -1;
813 return ret;
814 }
815
comps_doc_doctype_name_get(COMPS_Doc * doc)816 COMPS_Str* comps_doc_doctype_name_get(COMPS_Doc* doc) {
817 return (COMPS_Str*)COMPS_OBJECT_INCREF(doc->doctype_name);
818 }
comps_doc_doctype_pubid_get(COMPS_Doc * doc)819 COMPS_Str* comps_doc_doctype_pubid_get(COMPS_Doc* doc) {
820 return (COMPS_Str*)COMPS_OBJECT_INCREF(doc->doctype_pubid);
821 }
comps_doc_doctype_sysid_get(COMPS_Doc * doc)822 COMPS_Str* comps_doc_doctype_sysid_get(COMPS_Doc* doc) {
823 return (COMPS_Str*)COMPS_OBJECT_INCREF(doc->doctype_sysid);
824 }
comps_doc_doctype_name_set(COMPS_Doc * doc,COMPS_Str * val)825 void comps_doc_doctype_name_set(COMPS_Doc* doc, COMPS_Str *val) {
826 COMPS_OBJECT_REPLACE(doc->doctype_name, COMPS_Str, val);
827 }
comps_doc_doctype_sysid_set(COMPS_Doc * doc,COMPS_Str * val)828 void comps_doc_doctype_sysid_set(COMPS_Doc* doc, COMPS_Str *val) {
829 COMPS_OBJECT_REPLACE(doc->doctype_name, COMPS_Str, val);
830 }
comps_doc_doctype_pubid_set(COMPS_Doc * doc,COMPS_Str * val)831 void comps_doc_doctype_pubid_set(COMPS_Doc* doc, COMPS_Str *val) {
832 COMPS_OBJECT_REPLACE(doc->doctype_name, COMPS_Str, val);
833 }
834
835
comps_doc_arch_filter(COMPS_Doc * source,COMPS_ObjList * arches)836 COMPS_Doc* comps_doc_arch_filter(COMPS_Doc *source, COMPS_ObjList *arches) {
837 COMPS_ObjList *list, *arches2;
838 COMPS_Doc *ret;
839 COMPS_DocCategory *cat;
840 COMPS_DocGroup *group;
841 COMPS_DocEnv *env;
842
843 ret = COMPS_OBJECT_CREATE(COMPS_Doc, (COMPS_Object*[])
844 {(COMPS_Object*)source->encoding});
845 list = comps_doc_categories(source);
846 for (COMPS_ObjListIt *it = list->first; it != NULL; it = it->next) {
847 arches2 = comps_doccategory_arches((COMPS_DocCategory*)it->comps_obj);
848 if ((!arches2) || (__comps_objlist_intersected(arches, arches2))) {
849 cat = comps_doccategory_arch_filter((COMPS_DocCategory*)it->comps_obj,
850 arches);
851 comps_doc_add_category(ret, cat);
852 }
853 COMPS_OBJECT_DESTROY(arches2);
854 }
855 COMPS_OBJECT_DESTROY(list);
856 list = comps_doc_groups(source);
857 for (COMPS_ObjListIt *it = list->first; it != NULL; it = it->next) {
858 arches2 = comps_docgroup_arches((COMPS_DocGroup*)it->comps_obj);
859 if ((!arches2) || (__comps_objlist_intersected(arches, arches2))) {
860 group = comps_docgroup_arch_filter((COMPS_DocGroup*)it->comps_obj,
861 arches);
862 comps_doc_add_group(ret, group);
863 }
864 COMPS_OBJECT_DESTROY(arches2);
865 }
866 COMPS_OBJECT_DESTROY(list);
867 list = comps_doc_environments(source);
868 for (COMPS_ObjListIt *it = list->first; it != NULL; it = it->next) {
869 arches2 = comps_docenv_arches((COMPS_DocEnv*)it->comps_obj);
870 if ((!arches2) || (__comps_objlist_intersected(arches, arches2))) {
871 env = comps_docenv_arch_filter((COMPS_DocEnv*)it->comps_obj,
872 arches);
873 comps_doc_add_environment(ret, env);
874 }
875 COMPS_OBJECT_DESTROY(arches2);
876 }
877 COMPS_OBJECT_DESTROY(list);
878 return ret;
879 }
880
881 /*COMPS_Doc* comps_doc_set_lang(COMPS_Doc *comps, const char * lang) {
882 COMPS_OBJECT_DESTROY(comps->lang);
883 comps->lang = comps_str(lang);
884 }*/
885
comps_doc_listobjs_validate(COMPS_Object * object,COMPS_Object * objlist,COMPS_ValRuleGeneric ** rules)886 COMPS_ValGenResult* comps_doc_listobjs_validate(COMPS_Object *object,
887 COMPS_Object *objlist,
888 COMPS_ValRuleGeneric** rules) {
889 (void)object;
890 COMPS_ValGenResult *valres = NULL, *tmpres;
891 size_t x = 0;
892 char *str;
893 for (COMPS_ObjListIt *it = ((COMPS_ObjList*)objlist)->first;
894 it != NULL;
895 it = it->next, x++) {
896 tmpres = comps_validate_execute(it->comps_obj, rules);
897 if (tmpres->obj_info == &COMPS_ValErrResult_ObjInfo) {
898 if (!valres) {
899 valres = (COMPS_ValGenResult*)
900 COMPS_OBJECT_CREATE(COMPS_ValErrResult, NULL);
901 }
902 str = malloc(digits_count(x)*(sizeof(char)+2));
903 sprintf(str, "%zu.", x);
904 comps_valgenres_prefix(tmpres, str);
905 free(str);
906 comps_valgenres_concat(&valres, tmpres);
907 }
908 COMPS_OBJECT_DESTROY(tmpres);
909 }
910 if (!valres) {
911 valres = (COMPS_ValGenResult*)COMPS_OBJECT_CREATE(COMPS_ValOkResult,
912 NULL);
913 }
914 return valres;
915 }
916
comps_docgroups_validate(COMPS_Object * object,COMPS_Object * objlist)917 COMPS_ValGenResult* comps_docgroups_validate(COMPS_Object *object,
918 COMPS_Object *objlist) {
919 return comps_doc_listobjs_validate(object, objlist,
920 COMPS_DocGroup_ValidateRules);
921 }
comps_doccategories_validate(COMPS_Object * object,COMPS_Object * objlist)922 COMPS_ValGenResult* comps_doccategories_validate(COMPS_Object *object,
923 COMPS_Object *objlist) {
924 return comps_doc_listobjs_validate(object, objlist,
925 COMPS_DocCategory_ValidateRules);
926 }
comps_docenvs_validate(COMPS_Object * object,COMPS_Object * objlist)927 COMPS_ValGenResult* comps_docenvs_validate(COMPS_Object *object,
928 COMPS_Object *objlist) {
929 return comps_doc_listobjs_validate(object, objlist,
930 COMPS_DocEnv_ValidateRules);
931 }
932
933 COMPS_ValRuleGeneric* COMPS_Doc_ValidateRules[] = {
934 (COMPS_ValRuleGeneric*)&(COMPS_ValRuleList2){COMPS_VAL_RULE_LIST2,
935 .verbose_msg = "Groups check:",
936 .get_f = (COMPS_Object*(*)(COMPS_Object*))comps_doc_groups,
937 .check_f = &comps_docgroups_validate},
938 (COMPS_ValRuleGeneric*)&(COMPS_ValRuleList2){COMPS_VAL_RULE_LIST2,
939 .verbose_msg = "Categories check:",
940 .get_f = (COMPS_Object*(*)(COMPS_Object*))comps_doc_categories,
941 .check_f = &comps_doccategories_validate},
942 (COMPS_ValRuleGeneric*)&(COMPS_ValRuleList2){COMPS_VAL_RULE_LIST2,
943 .verbose_msg = "Environments check:",
944 .get_f = (COMPS_Object*(*)(COMPS_Object*))
945 comps_doc_environments,
946 .check_f = &comps_docenvs_validate},
947 NULL
948 };
949
950 COMPS_ObjectInfo COMPS_Doc_ObjInfo = {
951 .obj_size = sizeof(COMPS_Doc),
952 .constructor = &comps_doc_create_u,
953 .destructor = &comps_doc_destroy_u,
954 .copy = &comps_doc_copy_u,
955 .obj_cmp = &comps_doc_cmp_u
956 };
957