9 #include <rpm/header.h>
10 #include <rpm/rpmstring.h>
14 * Associate tag names with numeric values.
16 typedef const struct headerTagTableEntry_s * headerTagTableEntry;
17 struct headerTagTableEntry_s {
18 const char * name; /*!< Tag name. */
19 const char * shortname; /*!< "Human readable" short name. */
20 rpmTagVal val; /*!< Tag numeric value. */
21 rpmTagType type; /*!< Tag type. */
22 rpmTagReturnType retype; /*!< Tag return type. */
23 int extension; /*!< Extension or "real" tag */
26 #include "lib/tagtbl.C"
28 #define TABLESIZE (sizeof(rpmTagTable) / sizeof(rpmTagTable[0]) - 1)
29 static const int rpmTagTableSize = TABLESIZE;
31 static headerTagTableEntry tagsByName[TABLESIZE]; /*!< tags sorted by name. */
32 static headerTagTableEntry tagsByValue[TABLESIZE]; /*!< tags sorted by value. */
35 * Compare tag table entries by name.
36 * @param *avp tag table entry a
37 * @param *bvp tag table entry b
40 static int tagCmpName(const void * avp, const void * bvp)
42 headerTagTableEntry a = *(const headerTagTableEntry *) avp;
43 headerTagTableEntry b = *(const headerTagTableEntry *) bvp;
44 return strcmp(a->name, b->name);
48 * Compare tag table entries by value.
49 * @param *avp tag table entry a
50 * @param *bvp tag table entry b
53 static int tagCmpValue(const void * avp, const void * bvp)
55 headerTagTableEntry a = *(const headerTagTableEntry *) avp;
56 headerTagTableEntry b = *(const headerTagTableEntry *) bvp;
57 int ret = (a->val - b->val);
58 /* Make sure that sort is stable, longest name first. */
60 ret = (strlen(b->name) - strlen(a->name));
64 static pthread_once_t tagsLoaded = PTHREAD_ONCE_INIT;
66 /* Initialize tag by-value and by-name lookup tables */
67 static void loadTags(void)
69 for (int i = 0; i < rpmTagTableSize; i++) {
70 tagsByValue[i] = &rpmTagTable[i];
71 tagsByName[i] = &rpmTagTable[i];
74 qsort(tagsByValue, rpmTagTableSize, sizeof(*tagsByValue), tagCmpValue);
75 qsort(tagsByName, rpmTagTableSize, sizeof(*tagsByName), tagCmpName);
78 static headerTagTableEntry entryByTag(rpmTagVal tag)
80 headerTagTableEntry entry = NULL;
83 int u = rpmTagTableSize;
87 comparison = (tag - tagsByValue[i]->val);
91 } else if (comparison > 0) {
94 /* Make sure that the bsearch retrieve is stable. */
95 while (i > 0 && tag == tagsByValue[i-1]->val) {
98 entry = tagsByValue[i];
105 static headerTagTableEntry entryByName(const char *tag)
107 headerTagTableEntry entry = NULL;
110 int u = rpmTagTableSize;
114 comparison = rstrcasecmp(tag, tagsByName[i]->shortname);
116 if (comparison < 0) {
118 } else if (comparison > 0) {
121 entry = tagsByName[i];
128 const char * rpmTagGetName(rpmTagVal tag)
130 const char *name = "(unknown)";
131 const struct headerTagTableEntry_s *t;
133 pthread_once(&tagsLoaded, loadTags);
136 case RPMDBI_PACKAGES:
139 /* XXX make sure rpmdb indices are identically named. */
140 case RPMTAG_CONFLICTS:
141 name = "Conflictname";
149 if (t && t->shortname)
156 rpmTagType rpmTagGetType(rpmTagVal tag)
158 const struct headerTagTableEntry_s *t;
159 rpmTagType tagtype = RPM_NULL_TYPE;
161 pthread_once(&tagsLoaded, loadTags);
165 /* XXX this is dumb */
166 tagtype = (rpmTagType)(t->type | t->retype);
171 rpmTagVal rpmTagGetValue(const char * tagstr)
173 const struct headerTagTableEntry_s *t;
174 rpmTagType tagval = RPMTAG_NOT_FOUND;
176 pthread_once(&tagsLoaded, loadTags);
178 if (!rstrcasecmp(tagstr, "Packages"))
179 return RPMDBI_PACKAGES;
181 t = entryByName(tagstr);
188 rpmTagType rpmTagGetTagType(rpmTagVal tag)
190 return (rpmTagGetType(tag) & RPM_MASK_TYPE);
193 rpmTagReturnType rpmTagGetReturnType(rpmTagVal tag)
195 return (rpmTagGetType(tag) & RPM_MASK_RETURN_TYPE);
198 rpmTagClass rpmTagTypeGetClass(rpmTagType type)
201 switch (type & RPM_MASK_TYPE) {
207 tclass = RPM_NUMERIC_CLASS;
209 case RPM_STRING_TYPE:
210 case RPM_STRING_ARRAY_TYPE:
211 case RPM_I18NSTRING_TYPE:
212 tclass = RPM_STRING_CLASS;
215 tclass = RPM_BINARY_CLASS;
219 tclass = RPM_NULL_CLASS;
225 rpmTagClass rpmTagGetClass(rpmTagVal tag)
227 return rpmTagTypeGetClass(rpmTagGetTagType(tag));
230 int rpmTagGetNames(rpmtd tagnames, int fullname)
235 pthread_once(&tagsLoaded, loadTags);
237 if (tagnames == NULL || tagsByName == NULL)
240 rpmtdReset(tagnames);
241 tagnames->count = rpmTagTableSize;
242 tagnames->data = names = xmalloc(tagnames->count * sizeof(*names));
243 tagnames->type = RPM_STRING_ARRAY_TYPE;
244 tagnames->flags = RPMTD_ALLOCED | RPMTD_IMMUTABLE;
246 for (int i = 0; i < tagnames->count; i++) {
247 name = fullname ? tagsByName[i]->name :
248 tagsByName[i]->shortname;
251 return tagnames->count;