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 rpmTagVal val; /*!< Tag numeric value. */
19 rpmTagType type; /*!< Tag type. */
20 rpmTagReturnType retype; /*!< Tag return type. */
21 int extension; /*!< Extension or "real" tag */
24 #include "lib/tagtbl.C"
26 static const int rpmTagTableSize = sizeof(rpmTagTable) / sizeof(rpmTagTable[0]) - 1;
30 typedef struct headerTagIndices_s * headerTagIndices;
32 struct headerTagIndices_s {
33 int (*loadIndex) (headerTagTableEntry ** ipp, int * np,
34 int (*cmp) (const void * avp, const void * bvp));
35 /*!< load sorted tag index. */
36 headerTagTableEntry * byName; /*!< header tags sorted by name. */
37 int byNameSize; /*!< no. of entries. */
38 int (*byNameCmp) (const void * avp, const void * bvp); /*!< compare entries by name. */
39 rpmTagVal (*tagValue) (const char * name); /* return value from name. */
40 headerTagTableEntry * byValue; /*!< header tags sorted by value. */
41 int byValueSize; /*!< no. of entries. */
42 int (*byValueCmp) (const void * avp, const void * bvp); /*!< compare entries by value. */
43 const char * (*tagName) (rpmTagVal value); /* Return name from value. */
44 rpmTagType (*tagType) (rpmTagVal value); /* Return type from value. */
48 * Compare tag table entries by name.
49 * @param *avp tag table entry a
50 * @param *bvp tag table entry b
53 static int tagCmpName(const void * avp, const void * bvp)
55 headerTagTableEntry a = *(const headerTagTableEntry *) avp;
56 headerTagTableEntry b = *(const headerTagTableEntry *) bvp;
57 return strcmp(a->name, b->name);
61 * Compare tag table entries by value.
62 * @param *avp tag table entry a
63 * @param *bvp tag table entry b
66 static int tagCmpValue(const void * avp, const void * bvp)
68 headerTagTableEntry a = *(const headerTagTableEntry *) avp;
69 headerTagTableEntry b = *(const headerTagTableEntry *) bvp;
70 int ret = (a->val - b->val);
71 /* Make sure that sort is stable, longest name first. */
73 ret = (strlen(b->name) - strlen(a->name));
78 * Load/sort a tag index.
79 * @retval *ipp tag index
80 * @retval *np no. of tags
81 * @param cmp sort compare routine
84 static int tagLoadIndex(headerTagTableEntry ** ipp, int * np,
85 int (*cmp) (const void * avp, const void * bvp))
87 headerTagTableEntry tte, *ip;
90 ip = xcalloc(rpmTagTableSize, sizeof(*ip));
92 for (tte = (headerTagTableEntry)rpmTagTable; tte->name != NULL; tte++) {
96 assert(n == rpmTagTableSize);
99 qsort(ip, n, sizeof(*ip), cmp);
107 static const char * _tagName(rpmTagVal tag);
108 static rpmTagType _tagType(rpmTagVal tag);
109 static rpmTagVal _tagValue(const char * tagstr);
111 static struct headerTagIndices_s _rpmTags = {
113 NULL, 0, tagCmpName, _tagValue,
114 NULL, 0, tagCmpValue, _tagName, _tagType,
117 static headerTagIndices const rpmTags = &_rpmTags;
119 static const char * _tagName(rpmTagVal tag)
121 const char *name = "(unknown)";
122 const struct headerTagTableEntry_s *t;
123 int comparison, i, l, u;
125 if (_rpmTags.byValue == NULL)
126 tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue);
129 case RPMDBI_PACKAGES:
132 /* XXX make sure rpmdb indices are identically named. */
133 case RPMTAG_CONFLICTS:
134 name = "Conflictname";
141 if (_rpmTags.byValue == NULL)
144 u = _rpmTags.byValueSize;
147 t = _rpmTags.byValue[i];
149 comparison = (tag - t->val);
153 else if (comparison > 0)
156 /* Make sure that the bsearch retrieve is stable. */
157 while (i > 0 && tag == _rpmTags.byValue[i-1]->val) {
160 t = _rpmTags.byValue[i];
161 if (t->shortname != NULL)
171 static rpmTagType _tagType(rpmTagVal tag)
173 const struct headerTagTableEntry_s *t;
174 int comparison, i, l, u;
176 if (_rpmTags.byValue == NULL)
177 tagLoadIndex(&_rpmTags.byValue, &_rpmTags.byValueSize, tagCmpValue);
178 if (_rpmTags.byValue) {
180 u = _rpmTags.byValueSize;
183 t = _rpmTags.byValue[i];
185 comparison = (tag - t->val);
189 else if (comparison > 0)
192 /* Make sure that the bsearch retrieve is stable. */
193 while (i > 0 && t->val == _rpmTags.byValue[i-1]->val) {
196 t = _rpmTags.byValue[i];
197 /* XXX this is dumb */
198 return (rpmTagType)(t->type | t->retype);
202 return RPM_NULL_TYPE;
205 static rpmTagVal _tagValue(const char * tagstr)
207 const struct headerTagTableEntry_s *t;
208 int comparison, i, l, u;
210 if (!rstrcasecmp(tagstr, "Packages"))
211 return RPMDBI_PACKAGES;
213 if (_rpmTags.byName == NULL)
214 tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName);
215 if (_rpmTags.byName == NULL)
216 return RPMTAG_NOT_FOUND;
219 u = _rpmTags.byNameSize;
222 t = _rpmTags.byName[i];
224 comparison = rstrcasecmp(tagstr, t->shortname);
228 else if (comparison > 0)
233 return RPMTAG_NOT_FOUND;
236 const char * rpmTagGetName(rpmTagVal tag)
238 return ((*rpmTags->tagName)(tag));
241 rpmTagType rpmTagGetType(rpmTagVal tag)
243 return ((*rpmTags->tagType)(tag));
246 rpmTagType rpmTagGetTagType(rpmTagVal tag)
248 return (rpmTagType)((*rpmTags->tagType)(tag) & RPM_MASK_TYPE);
251 rpmTagReturnType rpmTagGetReturnType(rpmTagVal tag)
253 return ((*rpmTags->tagType)(tag) & RPM_MASK_RETURN_TYPE);
256 rpmTagClass rpmTagTypeGetClass(rpmTagType type)
259 switch (type & RPM_MASK_TYPE) {
265 tclass = RPM_NUMERIC_CLASS;
267 case RPM_STRING_TYPE:
268 case RPM_STRING_ARRAY_TYPE:
269 case RPM_I18NSTRING_TYPE:
270 tclass = RPM_STRING_CLASS;
273 tclass = RPM_BINARY_CLASS;
277 tclass = RPM_NULL_CLASS;
283 rpmTagClass rpmTagGetClass(rpmTagVal tag)
285 return rpmTagTypeGetClass(rpmTagGetTagType(tag));
288 rpmTagVal rpmTagGetValue(const char * tagstr)
290 return ((*rpmTags->tagValue)(tagstr));
293 int rpmTagGetNames(rpmtd tagnames, int fullname)
298 if (_rpmTags.byName == NULL)
299 tagLoadIndex(&_rpmTags.byName, &_rpmTags.byNameSize, tagCmpName);
300 if (tagnames == NULL ||_rpmTags.byName == NULL)
303 rpmtdReset(tagnames);
304 tagnames->count = _rpmTags.byNameSize;
305 tagnames->data = names = xmalloc(tagnames->count * sizeof(*names));
306 tagnames->type = RPM_STRING_ARRAY_TYPE;
307 tagnames->flags = RPMTD_ALLOCED | RPMTD_IMMUTABLE;
309 for (int i = 0; i < tagnames->count; i++) {
310 name = fullname ? _rpmTags.byName[i]->name :
311 _rpmTags.byName[i]->shortname;
314 return tagnames->count;