apply some patch for pythons rpm from opensource
[platform/upstream/rpm.git] / lib / rpmps.c
1 /**
2  * \file lib/rpmps.c
3  */
4
5 #include "system.h"
6
7 #include <inttypes.h>
8 #include <stdlib.h>
9
10 #include <rpm/rpmstring.h>
11 #include <rpm/rpmps.h>
12
13 #include "debug.h"
14
15 struct rpmps_s {
16     int numProblems;            /*!< Current probs array size. */
17     int numProblemsAlloced;     /*!< Allocated probs array size. */
18     rpmProblem *probs;          /*!< Array of pointers to specific problems. */
19     int nrefs;                  /*!< Reference count. */
20 };
21
22 struct rpmpsi_s {
23     int ix;
24     rpmps ps;
25 };
26
27
28 static rpmps rpmpsUnlink(rpmps ps)
29 {
30     if (ps) {
31         ps->nrefs--;
32     }
33     return NULL;
34 }
35
36 rpmps rpmpsLink(rpmps ps)
37 {
38     if (ps) {
39         ps->nrefs++;
40     }
41     return ps;
42 }
43
44 int rpmpsNumProblems(rpmps ps)
45 {
46     int numProblems = 0;
47     if (ps && ps->probs)
48         numProblems = ps->numProblems;
49     return numProblems;
50 }
51
52 rpmpsi rpmpsInitIterator(rpmps ps)
53 {
54     rpmpsi psi = NULL;
55     if (ps != NULL && ps->numProblems > 0) {
56         psi = xcalloc(1, sizeof(*psi));
57         psi->ps = rpmpsLink(ps);
58         psi->ix = -1;
59     }
60     return psi;
61 }
62
63 rpmpsi rpmpsFreeIterator(rpmpsi psi)
64 {
65     if (psi != NULL) {
66         rpmpsUnlink(psi->ps);
67         free(psi);
68     }
69     return NULL;
70 }
71
72 rpmProblem rpmpsiNext(rpmpsi psi)
73 {
74     rpmProblem p = NULL;
75     if (psi != NULL && psi->ps != NULL && ++psi->ix >= 0) {
76         rpmps ps = psi->ps;
77         if (psi->ix < ps->numProblems) {
78             p = ps->probs[psi->ix];
79         } else {
80             psi->ix = -1;
81         }
82     }
83     return p;
84 }
85
86 int rpmpsNextIterator(rpmpsi psi)
87 {
88     return (rpmpsiNext(psi) != NULL) ? psi->ix : -1;
89 }
90
91 rpmProblem rpmpsGetProblem(rpmpsi psi)
92 {
93     rpmProblem p = NULL;
94     if (psi != NULL && psi->ix >= 0 && psi->ix < rpmpsNumProblems(psi->ps)) {
95         p = psi->ps->probs[psi->ix];
96     } 
97     return p;
98 }
99
100 rpmps rpmpsCreate(void)
101 {
102     rpmps ps = xcalloc(1, sizeof(*ps));
103     return rpmpsLink(ps);
104 }
105
106 rpmps rpmpsFree(rpmps ps)
107 {
108     if (ps == NULL) return NULL;
109     if (ps->nrefs > 1) {
110         return rpmpsUnlink(ps);
111     }
112         
113     if (ps->probs) {
114         rpmpsi psi = rpmpsInitIterator(ps);
115         while (rpmpsNextIterator(psi) >= 0) {
116             rpmProblemFree(rpmpsGetProblem(psi));       
117         }
118         rpmpsFreeIterator(psi);
119         ps->probs = _free(ps->probs);
120     }
121     ps = _free(ps);
122     return NULL;
123 }
124
125 void rpmpsAppendProblem(rpmps ps, rpmProblem prob)
126 {
127     if (ps == NULL || prob == NULL) return;
128
129     if (ps->numProblems == ps->numProblemsAlloced) {
130         if (ps->numProblemsAlloced)
131             ps->numProblemsAlloced *= 2;
132         else
133             ps->numProblemsAlloced = 2;
134         ps->probs = xrealloc(ps->probs,
135                         ps->numProblemsAlloced * sizeof(*ps->probs));
136     }
137
138     ps->probs[ps->numProblems] = rpmProblemLink(prob);
139     ps->numProblems++;
140 }
141
142 /*
143  * TODO: filter out duplicates while merging. Also horribly inefficient... */
144 int rpmpsMerge(rpmps dest, rpmps src)
145 {
146     int rc = 0;
147     if (dest != NULL) {
148         rpmProblem p;
149         rpmpsi spi = rpmpsInitIterator(src);
150         while ((p = rpmpsiNext(spi)) != NULL) {
151             rpmpsAppendProblem(dest, p);
152             rc++;
153         }
154         rpmpsFreeIterator(spi);
155     }
156     return rc;
157 }
158
159 void rpmpsPrint(FILE *fp, rpmps ps)
160 {
161     rpmProblem p;
162     rpmpsi psi = rpmpsInitIterator(ps);
163     FILE *f = (fp != NULL) ? fp : stderr;
164
165     while ((p = rpmpsiNext(psi))) {
166         char *msg = rpmProblemString(p);
167         fprintf(f, "\t%s\n", msg);
168         free(msg);
169     }
170     rpmpsFreeIterator(psi);
171 }
172