4 #include <rpm/rpmstring.h>
5 #include <rpm/rpmpgp.h>
6 #include <rpm/rpmstrpool.h>
7 #include "lib/misc.h" /* format function prototypes */
13 rpmtd td = xmalloc(sizeof(*td));
18 rpmtd rpmtdFree(rpmtd td)
20 /* permit free on NULL td */
28 void rpmtdReset(rpmtd td)
31 memset(td, 0, sizeof(*td));
36 void rpmtdFreeData(rpmtd td)
38 if (td && td->data && td->flags & RPMTD_ALLOCED) {
39 if (td->flags & RPMTD_PTR_ALLOCED) {
40 char **data = td->data;
41 for (int i = 0; i < td->count; i++) {
50 rpm_count_t rpmtdCount(rpmtd td)
52 rpm_count_t count = 0;
54 /* fix up for binary type abusing count as data length */
55 count = (td->type == RPM_BIN_TYPE) ? 1 : td->count;
60 rpm_count_t rpmtdSize(rpmtd td)
62 return (td != NULL) ? td->size : 0;
65 rpmTagVal rpmtdTag(rpmtd td)
67 return (td != NULL) ? td->tag : 0;
70 rpmTagType rpmtdType(rpmtd td)
72 return (td != NULL) ? td->type : 0;
75 rpmTagClass rpmtdClass(rpmtd td)
77 return (td != NULL) ? rpmTagTypeGetClass(td->type) : 0;
80 rpmtdFlags rpmtdGetFlags(rpmtd td)
82 return (td != NULL) ? td->flags : 0;
85 int rpmtdGetIndex(rpmtd td)
87 return (td != NULL) ? td->ix : -1;
90 int rpmtdSetIndex(rpmtd td, int index)
92 if (td == NULL || index < 0 || index >= rpmtdCount(td)) {
99 int rpmtdInit(rpmtd td)
104 /* XXX check that this is an array type? */
109 int rpmtdNext(rpmtd td)
113 if (td != NULL && ++td->ix >= 0) {
114 if (td->ix < rpmtdCount(td)) {
123 uint32_t *rpmtdNextUint32(rpmtd td)
125 uint32_t *res = NULL;
126 if (rpmtdNext(td) >= 0) {
127 res = rpmtdGetUint32(td);
132 uint64_t *rpmtdNextUint64(rpmtd td)
134 uint64_t *res = NULL;
135 if (rpmtdNext(td) >= 0) {
136 res = rpmtdGetUint64(td);
141 const char *rpmtdNextString(rpmtd td)
143 const char *res = NULL;
144 if (rpmtdNext(td) >= 0) {
145 res = rpmtdGetString(td);
150 char * rpmtdGetChar(rpmtd td)
154 if (td != NULL && td->type == RPM_CHAR_TYPE) {
155 int ix = (td->ix >= 0 ? td->ix : 0);
156 res = (char *) td->data + ix;
160 uint16_t * rpmtdGetUint16(rpmtd td)
162 uint16_t *res = NULL;
164 if (td != NULL && td->type == RPM_INT16_TYPE) {
165 int ix = (td->ix >= 0 ? td->ix : 0);
166 res = (uint16_t *) td->data + ix;
171 uint32_t * rpmtdGetUint32(rpmtd td)
173 uint32_t *res = NULL;
175 if (td != NULL && td->type == RPM_INT32_TYPE) {
176 int ix = (td->ix >= 0 ? td->ix : 0);
177 res = (uint32_t *) td->data + ix;
182 uint64_t * rpmtdGetUint64(rpmtd td)
184 uint64_t *res = NULL;
186 if (td != NULL && td->type == RPM_INT64_TYPE) {
187 int ix = (td->ix >= 0 ? td->ix : 0);
188 res = (uint64_t *) td->data + ix;
193 const char * rpmtdGetString(rpmtd td)
195 const char *str = NULL;
200 if (td->type == RPM_STRING_TYPE) {
201 str = (const char *) td->data;
202 } else if (td->type == RPM_STRING_ARRAY_TYPE ||
203 td->type == RPM_I18NSTRING_TYPE) {
204 /* XXX TODO: check for array bounds */
205 int ix = (td->ix >= 0 ? td->ix : 0);
206 str = *((const char**) td->data + ix);
211 uint64_t rpmtdGetNumber(rpmtd td)
214 int ix = (td->ix >= 0 ? td->ix : 0);
221 val = *((uint64_t *) td->data + ix);
224 val = *((uint32_t *) td->data + ix);
227 val = *((uint16_t *) td->data + ix);
231 val = *((uint8_t *) td->data + ix);
239 char *rpmtdFormat(rpmtd td, rpmtdFormats fmt, const char *errmsg)
241 headerFmt ext = rpmHeaderFormatByValue(fmt);
242 const char *err = NULL;
246 str = rpmHeaderFormatCall(ext, td);
248 err = _("Unknown format");
258 int rpmtdSetTag(rpmtd td, rpmTagVal tag)
260 rpmTagType newtype = rpmTagGetTagType(tag);
268 * - is the new tag valid at all
269 * - if changing tag of non-empty container, require matching type
271 if (newtype == RPM_NULL_TYPE)
274 if (td->data || td->count > 0) {
275 if (rpmTagGetTagType(td->tag) != rpmTagGetTagType(tag)) {
288 static inline int rpmtdSet(rpmtd td, rpmTagVal tag, rpmTagType type,
289 rpm_constdata_t data, rpm_count_t count)
296 * Discards const, but we won't touch the data (even rpmtdFreeData()
297 * wont free it as allocation flags aren't set) so it's "ok".
298 * XXX: Should there be a separate RPMTD_FOO flag for "user data"?
300 td->data = (void *) data;
304 int rpmtdFromUint8(rpmtd td, rpmTagVal tag, uint8_t *data, rpm_count_t count)
306 rpmTagType type = rpmTagGetTagType(tag);
307 rpmTagReturnType retype = rpmTagGetReturnType(tag);
313 * BIN type is really just an uint8_t array internally, it's just
314 * treated specially otherwise.
319 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
328 return rpmtdSet(td, tag, type, data, count);
331 int rpmtdFromUint16(rpmtd td, rpmTagVal tag, uint16_t *data, rpm_count_t count)
333 rpmTagType type = rpmTagGetTagType(tag);
334 rpmTagReturnType retype = rpmTagGetReturnType(tag);
335 if (type != RPM_INT16_TYPE || count < 1)
337 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
340 return rpmtdSet(td, tag, type, data, count);
343 int rpmtdFromUint32(rpmtd td, rpmTagVal tag, uint32_t *data, rpm_count_t count)
345 rpmTagType type = rpmTagGetTagType(tag);
346 rpmTagReturnType retype = rpmTagGetReturnType(tag);
347 if (type != RPM_INT32_TYPE || count < 1)
349 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
352 return rpmtdSet(td, tag, type, data, count);
355 int rpmtdFromUint64(rpmtd td, rpmTagVal tag, uint64_t *data, rpm_count_t count)
357 rpmTagType type = rpmTagGetTagType(tag);
358 rpmTagReturnType retype = rpmTagGetReturnType(tag);
359 if (type != RPM_INT64_TYPE || count < 1)
361 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
364 return rpmtdSet(td, tag, type, data, count);
367 int rpmtdFromString(rpmtd td, rpmTagVal tag, const char *data)
369 rpmTagType type = rpmTagGetTagType(tag);
372 if (type == RPM_STRING_TYPE) {
373 rc = rpmtdSet(td, tag, type, data, 1);
374 } else if (type == RPM_STRING_ARRAY_TYPE) {
375 rc = rpmtdSet(td, tag, type, &data, 1);
381 int rpmtdFromStringArray(rpmtd td, rpmTagVal tag, const char **data, rpm_count_t count)
383 rpmTagType type = rpmTagGetTagType(tag);
384 if (type != RPM_STRING_ARRAY_TYPE || count < 1)
386 if (type == RPM_STRING_TYPE && count != 1)
389 return rpmtdSet(td, tag, type, data, count);
392 int rpmtdFromArgv(rpmtd td, rpmTagVal tag, ARGV_t argv)
394 int count = argvCount(argv);
395 rpmTagType type = rpmTagGetTagType(tag);
397 if (type != RPM_STRING_ARRAY_TYPE || count < 1)
400 return rpmtdSet(td, tag, type, argv, count);
403 int rpmtdFromArgi(rpmtd td, rpmTagVal tag, ARGI_t argi)
405 int count = argiCount(argi);
406 rpmTagType type = rpmTagGetTagType(tag);
407 rpmTagReturnType retype = rpmTagGetReturnType(tag);
409 if (type != RPM_INT32_TYPE || retype != RPM_ARRAY_RETURN_TYPE || count < 1)
412 return rpmtdSet(td, tag, type, argiData(argi), count);
415 rpmtd rpmtdDup(rpmtd td)
424 /* TODO: permit other types too */
425 if (td->type != RPM_STRING_ARRAY_TYPE && td->type != RPM_I18NSTRING_TYPE) {
429 /* deep-copy container and data, drop immutable flag */
431 memcpy(newtd, td, sizeof(*td));
432 newtd->flags &= ~(RPMTD_IMMUTABLE);
434 newtd->flags |= (RPMTD_ALLOCED | RPMTD_PTR_ALLOCED);
435 newtd->data = data = xmalloc(td->count * sizeof(*data));
436 while ((i = rpmtdNext(td)) >= 0) {
437 data[i] = xstrdup(rpmtdGetString(td));
443 rpmsid * rpmtdToPool(rpmtd td, rpmstrPool pool)
448 const char **strings = td->data;
450 case RPM_STRING_ARRAY_TYPE:
451 case RPM_I18NSTRING_TYPE:
452 sids = xmalloc(td->count * sizeof(*sids));
453 for (rpm_count_t i = 0; i < td->count; i++)
454 sids[i] = rpmstrPoolId(pool, strings[i], 1);