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 */
22 /* XXX should we free data too - a flag maybe? */
28 void rpmtdReset(rpmtd td)
32 memset(td, 0, sizeof(*td));
36 void rpmtdFreeData(rpmtd td)
40 if (td->flags & RPMTD_ALLOCED) {
41 if (td->flags & RPMTD_PTR_ALLOCED) {
42 assert(td->data != NULL);
43 char **data = td->data;
44 for (int i = 0; i < td->count; i++) {
53 rpm_count_t rpmtdCount(rpmtd td)
56 /* fix up for binary type abusing count as data length */
57 return (td->type == RPM_BIN_TYPE) ? 1 : td->count;
60 rpmTagVal rpmtdTag(rpmtd td)
66 rpmTagType rpmtdType(rpmtd td)
72 rpmTagClass rpmtdClass(rpmtd td)
75 return rpmTagTypeGetClass(td->type);
78 rpmtdFlags rpmtdGetFlags(rpmtd td)
80 return (td != NULL) ? td->flags : 0;
83 int rpmtdGetIndex(rpmtd td)
89 int rpmtdSetIndex(rpmtd td, int index)
93 if (index < 0 || index >= rpmtdCount(td)) {
100 int rpmtdInit(rpmtd td)
104 /* XXX check that this is an array type? */
109 int rpmtdNext(rpmtd td)
116 if (td->ix < rpmtdCount(td)) {
125 uint32_t *rpmtdNextUint32(rpmtd td)
128 uint32_t *res = NULL;
129 if (rpmtdNext(td) >= 0) {
130 res = rpmtdGetUint32(td);
135 uint64_t *rpmtdNextUint64(rpmtd td)
138 uint64_t *res = NULL;
139 if (rpmtdNext(td) >= 0) {
140 res = rpmtdGetUint64(td);
145 const char *rpmtdNextString(rpmtd td)
148 const char *res = NULL;
149 if (rpmtdNext(td) >= 0) {
150 res = rpmtdGetString(td);
155 char * rpmtdGetChar(rpmtd td)
161 if (td->type == RPM_CHAR_TYPE) {
162 int ix = (td->ix >= 0 ? td->ix : 0);
163 res = (char *) td->data + ix;
167 uint16_t * rpmtdGetUint16(rpmtd td)
169 uint16_t *res = NULL;
173 if (td->type == RPM_INT16_TYPE) {
174 int ix = (td->ix >= 0 ? td->ix : 0);
175 res = (uint16_t *) td->data + ix;
180 uint32_t * rpmtdGetUint32(rpmtd td)
182 uint32_t *res = NULL;
186 if (td->type == RPM_INT32_TYPE) {
187 int ix = (td->ix >= 0 ? td->ix : 0);
188 res = (uint32_t *) td->data + ix;
193 uint64_t * rpmtdGetUint64(rpmtd td)
195 uint64_t *res = NULL;
199 if (td->type == RPM_INT64_TYPE) {
200 int ix = (td->ix >= 0 ? td->ix : 0);
201 res = (uint64_t *) td->data + ix;
206 const char * rpmtdGetString(rpmtd td)
208 const char *str = NULL;
212 if (td->type == RPM_STRING_TYPE) {
213 str = (const char *) td->data;
214 } else if (td->type == RPM_STRING_ARRAY_TYPE ||
215 td->type == RPM_I18NSTRING_TYPE) {
216 /* XXX TODO: check for array bounds */
217 int ix = (td->ix >= 0 ? td->ix : 0);
218 str = *((const char**) td->data + ix);
223 uint64_t rpmtdGetNumber(rpmtd td)
227 int ix = (td->ix >= 0 ? td->ix : 0);
231 val = *((uint64_t *) td->data + ix);
234 val = *((uint32_t *) td->data + ix);
237 val = *((uint16_t *) td->data + ix);
241 val = *((uint8_t *) td->data + ix);
249 char *rpmtdFormat(rpmtd td, rpmtdFormats fmt, const char *errmsg)
251 headerTagFormatFunction func = rpmHeaderFormatFuncByValue(fmt);
252 const char *err = NULL;
258 err = _("Unknown format");
268 int rpmtdSetTag(rpmtd td, rpmTagVal tag)
271 rpmTagType newtype = rpmTagGetTagType(tag);
276 * - is the new tag valid at all
277 * - if changing tag of non-empty container, require matching type
279 if (newtype == RPM_NULL_TYPE)
282 if (td->data || td->count > 0) {
283 if (rpmTagGetTagType(td->tag) != rpmTagGetTagType(tag)) {
296 static inline int rpmtdSet(rpmtd td, rpmTagVal tag, rpmTagType type,
297 rpm_constdata_t data, rpm_count_t count)
304 * Discards const, but we won't touch the data (even rpmtdFreeData()
305 * wont free it as allocation flags aren't set) so it's "ok".
306 * XXX: Should there be a separate RPMTD_FOO flag for "user data"?
308 td->data = (void *) data;
312 int rpmtdFromUint8(rpmtd td, rpmTagVal tag, uint8_t *data, rpm_count_t count)
314 rpmTagType type = rpmTagGetTagType(tag);
315 rpmTagReturnType retype = rpmTagGetReturnType(tag);
321 * BIN type is really just an uint8_t array internally, it's just
322 * treated specially otherwise.
327 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
336 return rpmtdSet(td, tag, type, data, count);
339 int rpmtdFromUint16(rpmtd td, rpmTagVal tag, uint16_t *data, rpm_count_t count)
341 rpmTagType type = rpmTagGetTagType(tag);
342 rpmTagReturnType retype = rpmTagGetReturnType(tag);
343 if (type != RPM_INT16_TYPE || count < 1)
345 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
348 return rpmtdSet(td, tag, type, data, count);
351 int rpmtdFromUint32(rpmtd td, rpmTagVal tag, uint32_t *data, rpm_count_t count)
353 rpmTagType type = rpmTagGetTagType(tag);
354 rpmTagReturnType retype = rpmTagGetReturnType(tag);
355 if (type != RPM_INT32_TYPE || count < 1)
357 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
360 return rpmtdSet(td, tag, type, data, count);
363 int rpmtdFromUint64(rpmtd td, rpmTagVal tag, uint64_t *data, rpm_count_t count)
365 rpmTagType type = rpmTagGetTagType(tag);
366 rpmTagReturnType retype = rpmTagGetReturnType(tag);
367 if (type != RPM_INT64_TYPE || count < 1)
369 if (retype != RPM_ARRAY_RETURN_TYPE && count > 1)
372 return rpmtdSet(td, tag, type, data, count);
375 int rpmtdFromString(rpmtd td, rpmTagVal tag, const char *data)
377 rpmTagType type = rpmTagGetTagType(tag);
380 if (type == RPM_STRING_TYPE) {
381 rc = rpmtdSet(td, tag, type, data, 1);
382 } else if (type == RPM_STRING_ARRAY_TYPE) {
383 rc = rpmtdSet(td, tag, type, &data, 1);
389 int rpmtdFromStringArray(rpmtd td, rpmTagVal tag, const char **data, rpm_count_t count)
391 rpmTagType type = rpmTagGetTagType(tag);
392 if (type != RPM_STRING_ARRAY_TYPE || count < 1)
394 if (type == RPM_STRING_TYPE && count != 1)
397 return rpmtdSet(td, tag, type, data, count);
400 int rpmtdFromArgv(rpmtd td, rpmTagVal tag, ARGV_t argv)
402 int count = argvCount(argv);
403 rpmTagType type = rpmTagGetTagType(tag);
405 if (type != RPM_STRING_ARRAY_TYPE || count < 1)
408 return rpmtdSet(td, tag, type, argv, count);
411 int rpmtdFromArgi(rpmtd td, rpmTagVal tag, ARGI_t argi)
413 int count = argiCount(argi);
414 rpmTagType type = rpmTagGetTagType(tag);
415 rpmTagReturnType retype = rpmTagGetReturnType(tag);
417 if (type != RPM_INT32_TYPE || retype != RPM_ARRAY_RETURN_TYPE || count < 1)
420 return rpmtdSet(td, tag, type, argiData(argi), count);
423 rpmtd rpmtdDup(rpmtd td)
430 /* TODO: permit other types too */
431 if (td->type != RPM_STRING_ARRAY_TYPE && td->type != RPM_I18NSTRING_TYPE) {
435 /* deep-copy container and data, drop immutable flag */
437 memcpy(newtd, td, sizeof(*td));
438 newtd->flags &= ~(RPMTD_IMMUTABLE);
440 newtd->flags |= (RPMTD_ALLOCED | RPMTD_PTR_ALLOCED);
441 newtd->data = data = xmalloc(td->count * sizeof(*data));
442 while ((i = rpmtdNext(td)) >= 0) {
443 data[i] = xstrdup(rpmtdGetString(td));
449 rpmsid * rpmtdToPool(rpmtd td, rpmstrPool pool)
454 const char **strings = td->data;
456 case RPM_STRING_ARRAY_TYPE:
457 case RPM_I18NSTRING_TYPE:
458 sids = xmalloc(td->count * sizeof(*sids));
459 for (rpm_count_t i = 0; i < td->count; i++)
460 sids[i] = rpmstrPoolId(pool, strings[i], 1);