1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
/*
* filelist.c
*
* Copyright (c) 2012 Pacman Development Team <pacman-dev@archlinux.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
/* libalpm */
#include "filelist.h"
/* Returns a set operation on the provided two lists of files.
* Pre-condition: both lists are sorted!
* When done, free the list but NOT the contained data.
*
* Operations:
* DIFFERENCE - a difference operation is performed. filesA - filesB.
* INTERSECT - an intersection operation is performed. filesA & filesB.
*/
alpm_list_t *_alpm_filelist_operation(alpm_filelist_t *filesA,
alpm_filelist_t *filesB, enum filelist_op operation)
{
alpm_list_t *ret = NULL;
size_t ctrA = 0, ctrB = 0;
while(ctrA < filesA->count && ctrB < filesB->count) {
alpm_file_t *fileA = filesA->files + ctrA;
alpm_file_t *fileB = filesB->files + ctrB;
const char *strA = fileA->name;
const char *strB = fileB->name;
/* skip directories, we don't care about them */
if(strA[strlen(strA)-1] == '/') {
ctrA++;
} else if(strB[strlen(strB)-1] == '/') {
ctrB++;
} else {
int cmp = strcmp(strA, strB);
if(cmp < 0) {
if(operation == DIFFERENCE) {
/* item only in filesA, qualifies as a difference */
ret = alpm_list_add(ret, fileA);
}
ctrA++;
} else if(cmp > 0) {
ctrB++;
} else {
if(operation == INTERSECT) {
/* item in both, qualifies as an intersect */
ret = alpm_list_add(ret, fileA);
}
ctrA++;
ctrB++;
}
}
}
/* if doing a difference, ensure we have completely emptied pA */
while(operation == DIFFERENCE && ctrA < filesA->count) {
alpm_file_t *fileA = filesA->files + ctrA;
const char *strA = fileA->name;
/* skip directories */
if(strA[strlen(strA)-1] != '/') {
ret = alpm_list_add(ret, fileA);
}
ctrA++;
}
return ret;
}
/* Helper function for comparing files list entries
*/
int _alpm_files_cmp(const void *f1, const void *f2)
{
const alpm_file_t *file1 = f1;
const alpm_file_t *file2 = f2;
return strcmp(file1->name, file2->name);
}
alpm_file_t *alpm_filelist_contains(alpm_filelist_t *filelist,
const char *path)
{
alpm_file_t key;
if(!filelist) {
return NULL;
}
key.name = (char *)path;
return bsearch(&key, filelist->files, filelist->count,
sizeof(alpm_file_t), _alpm_files_cmp);
}
/* vim: set ts=2 sw=2 noet: */
|