7 #include <rpm/header.h>
8 #include <rpm/rpmstring.h>
12 * Associate tag names with numeric values.
14 typedef const struct headerTagTableEntry_s * headerTagTableEntry;
15 struct headerTagTableEntry_s {
16 const char * name; /*!< Tag name. */
17 const char * shortname; /*!< "Human readable" short name. */
18 rpmTag val; /*!< Tag numeric value. */
19 rpmTagType type; /*!< Tag type. */
20 int extension; /*!< Extension or "real" tag */
23 #include "lib/tagtbl.c"
25 static const int rpmTagTableSize = sizeof(rpmTagTable) / sizeof(rpmTagTable[0]) - 1;
29 typedef struct headerTagIndices_s * headerTagIndices;
31 struct headerTagIndices_s {
32 int (*loadIndex) (headerTagTableEntry ** ipp, int * np,
33 int (*cmp) (const void * avp, const void * bvp));
34 /*!< load sorted tag index. */
35 headerTagTableEntry * byName; /*!< header tags sorted by name. */
36 int byNameSize; /*!< no. of entries. */
37 int (*byNameCmp) (const void * avp, const void * bvp); /*!< compare entries by name. */
38 rpmTag (*tagValue) (const char * name); /* return value from name. */
39 headerTagTableEntry * byValue; /*!< header tags sorted by value. */
40 int byValueSize; /*!< no. of entries. */
41 int (*byValueCmp) (const void * avp, const void * bvp); /*!< compare entries by value. */
42 const char * (*tagName) (rpmTag value); /* Return name from value. */
43 rpmTagType (*tagType) (rpmTag value); /* Return type from value. */
47 * Compare tag table entries by name.
48 * @param *avp tag table entry a
49 * @param *bvp tag table entry b
52 static int tagCmpName(const void * avp, const void * bvp)
54 headerTagTableEntry a = *(const headerTagTableEntry *) avp;
55 headerTagTableEntry b = *(const headerTagTableEntry *) bvp;
56 return strcmp(a->name, b->name);
60 * Compare tag table entries by value.
61 * @param *avp tag table entry a
62 * @param *bvp tag table entry b
65 static int tagCmpValue(const void * avp, const void * bvp)
67 headerTagTableEntry a = *(const headerTagTableEntry *) avp;
68 headerTagTableEntry b = *(const headerTagTableEntry *) bvp;
69 int ret = (a->val - b->val);
70 /* Make sure that sort is stable, longest name first. */
72 ret = (strlen(b->name) - strlen(a->name));
77 * Load/sort a tag index.
78 * @retval *ipp tag index
79 * @retval *np no. of tags
80 * @param cmp sort compare routine
83 static int tagLoadIndex(headerTagTableEntry ** ipp, int * np,
84 int (*cmp) (const void * avp, const void * bvp))
86 headerTagTableEntry tte, *ip;
89 ip = xcalloc(rpmTagTableSize, sizeof(*ip));
91 for (tte = (headerTagTableEntry)rpmTagTable; tte->name != NULL; tte++) {
95 assert(n == rpmTagTableSize);
98 qsort(ip, n, sizeof(*ip), cmp);
106 static const char * _tagName(rpmTag tag);
107 static rpmTagType _tagType(rpmTag tag);
108 static rpmTag _tagValue(const char * tagstr);
110 static struct headerTagIndices_s _rpmTags = {
112 NULL, 0, tagCmpName, _tagValue,
113 NULL, 0, tagCmpValue, _tagName, _tagType,
116 static headerTagIndices const rpmTags = &_rpmTags;
118 static const char * _tagName(rpmTag tag)
120 const char *name = "(unknown)";
121 const struct headerTagTableEntry_s *t;
122 int comparison, i, l, u;
125 if (_rpmTags.byValue == NULL)
126 xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue);
129 case RPMDBI_PACKAGES:
141 case RPMDBI_AVAILABLE:
154 /* XXX make sure rpmdb indices are identically named. */
155 case RPMTAG_CONFLICTS:
156 name = "Conflictname";
163 if (_rpmTags.byValue == NULL)
166 u = _rpmTags.byValueSize;
169 t = _rpmTags.byValue[i];
171 comparison = (tag - t->val);
175 else if (comparison > 0)
178 /* Make sure that the bsearch retrieve is stable. */
179 while (i > 0 && tag == _rpmTags.byValue[i-1]->val) {
182 t = _rpmTags.byValue[i];
183 if (t->shortname != NULL)
193 static rpmTagType _tagType(rpmTag tag)
195 const struct headerTagTableEntry_s *t;
196 int comparison, i, l, u;
199 if (_rpmTags.byValue == NULL)
200 xx = tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue);
203 case RPMDBI_PACKAGES:
207 case RPMDBI_AVAILABLE:
213 if (_rpmTags.byValue == NULL)
216 u = _rpmTags.byValueSize;
219 t = _rpmTags.byValue[i];
221 comparison = (tag - t->val);
225 else if (comparison > 0)
228 /* Make sure that the bsearch retrieve is stable. */
229 while (i > 0 && t->val == _rpmTags.byValue[i-1]->val) {
232 t = _rpmTags.byValue[i];
238 return RPM_NULL_TYPE;
241 static rpmTag _tagValue(const char * tagstr)
243 const struct headerTagTableEntry_s *t;
244 int comparison, i, l, u;
247 if (!rstrcasecmp(tagstr, "Packages"))
248 return RPMDBI_PACKAGES;
249 if (!rstrcasecmp(tagstr, "Depends"))
250 return RPMDBI_DEPENDS;
251 if (!rstrcasecmp(tagstr, "Added"))
253 if (!rstrcasecmp(tagstr, "Removed"))
254 return RPMDBI_REMOVED;
255 if (!rstrcasecmp(tagstr, "Available"))
256 return RPMDBI_AVAILABLE;
257 if (!rstrcasecmp(tagstr, "Hdlist"))
258 return RPMDBI_HDLIST;
259 if (!rstrcasecmp(tagstr, "Arglist"))
260 return RPMDBI_ARGLIST;
261 if (!rstrcasecmp(tagstr, "Ftswalk"))
262 return RPMDBI_FTSWALK;
264 if (_rpmTags.byName == NULL)
265 xx = tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName);
266 if (_rpmTags.byName == NULL)
267 return RPMTAG_NOT_FOUND;
270 u = _rpmTags.byNameSize;
273 t = _rpmTags.byName[i];
275 comparison = rstrcasecmp(tagstr, t->shortname);
279 else if (comparison > 0)
284 return RPMTAG_NOT_FOUND;
287 const char * rpmTagGetName(rpmTag tag)
289 return ((*rpmTags->tagName)(tag));
292 rpmTagType rpmTagGetType(rpmTag tag)
294 return ((*rpmTags->tagType)(tag));
297 rpmTagClass rpmTagTypeGetClass(rpmTagType type)
300 switch (type & RPM_MASK_TYPE) {
306 class = RPM_NUMERIC_CLASS;
308 case RPM_STRING_TYPE:
309 case RPM_STRING_ARRAY_TYPE:
310 case RPM_I18NSTRING_TYPE:
311 class = RPM_STRING_CLASS;
314 class = RPM_BINARY_CLASS;
318 class = RPM_NULL_CLASS;
324 rpmTagClass rpmTagGetClass(rpmTag tag)
326 return rpmTagTypeGetClass(rpmTagGetType(tag));
329 rpmTag rpmTagGetValue(const char * tagstr)
331 return ((*rpmTags->tagValue)(tagstr));
334 int rpmTagGetNames(rpmtd tagnames, int fullname)
339 if (_rpmTags.byName == NULL)
340 tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName);
341 if (tagnames == NULL ||_rpmTags.byName == NULL)
344 rpmtdReset(tagnames);
345 tagnames->count = _rpmTags.byNameSize;
346 tagnames->data = names = xmalloc(tagnames->count * sizeof(*names));
347 tagnames->type = RPM_STRING_ARRAY_TYPE;
348 tagnames->flags = RPMTD_ALLOCED | RPMTD_IMMUTABLE;
350 for (int i = 0; i < tagnames->count; i++) {
351 name = fullname ? _rpmTags.byName[i]->name :
352 _rpmTags.byName[i]->shortname;
355 return tagnames->count;