Add type-safe headerPutFoo() methods for supported tag data types
authorPanu Matilainen <pmatilai@redhat.com>
Thu, 19 Jun 2008 12:41:58 +0000 (15:41 +0300)
committerPanu Matilainen <pmatilai@redhat.com>
Thu, 19 Jun 2008 12:41:58 +0000 (15:41 +0300)
- requiring all access through rpmtdFromFoo() just adds unnecessary
  indirection and pain for little gain, the header is fairly intelligent
  when it comes to inserting data
- this gives us various benefits over the old headerAddEntry() interface too:
  + basic type checking done by compiler
  + extra sanity checking (ie you can't add string data to integer tags,
    don't permit adding more than one entry to non-array data etc)
  + "do the right thing" approach - add / append as needed and supported
    by various types
  + headerPutString() can now be used on both single strings and string
    arrays making the interface much nicer for the rather common case of
    appending strings one by one to string array tags

lib/header.c
lib/header.h

index 0c36651..3ed0d0e 100644 (file)
@@ -1584,6 +1584,99 @@ int headerPut(Header h, rpmtd td, headerPutFlags flags)
     return rc;
 }
 
+/*
+ * Sanity check data types against tag table before putting. Assume
+ * append on all array-types.
+ */
+static int headerPutType(Header h, rpmTag tag, rpmTagType reqtype,
+                       rpm_constdata_t data, rpm_count_t size)
+{
+    struct rpmtd_s td;
+    rpmTagType type = rpmTagGetType(tag);
+    headerPutFlags flags = HEADERPUT_APPEND; 
+    int valid = 1;
+
+    /* Basic sanity checks: type must match and there must be data to put */
+    if (td.type != reqtype || size < 1 || data == NULL || h == NULL) {
+       valid = 0;
+    }
+
+    /*
+     * Non-array types can't be appended to. Binary types use size
+     * for data length, for other non-array types size must be 1.
+     */
+    if ((type & RPM_MASK_RETURN_TYPE) != RPM_ARRAY_RETURN_TYPE) {
+       flags = HEADERPUT_DEFAULT;
+       if ((type & RPM_MASK_TYPE) != RPM_BIN_TYPE && size != 1) {
+           valid = 0;
+       }
+    }
+
+    if (valid) {
+       rpmtdReset(&td);
+       td.tag = tag;
+       td.type = type & RPM_MASK_TYPE;
+       td.data = (void *) data;
+       td.count = size;
+
+       valid = headerPut(h, &td, flags);
+    }
+
+    return valid;
+}
+       
+int headerPutString(Header h, rpmTag tag, const char *str)
+{
+    rpmTagType type = rpmTagGetType(tag) & RPM_MASK_TYPE;
+    const void *sptr = NULL;
+
+    /* string arrays expect char **, arrange that */
+    if (type == RPM_STRING_ARRAY_TYPE) {
+       sptr = &str;
+    } else if (type == RPM_STRING_TYPE) {
+       sptr = str;
+    } else {
+       return 0;
+    }
+
+    return headerPutType(h, tag, type, sptr, 1);
+}
+
+int headerPutStringArray(Header h, rpmTag tag, const char **array, rpm_count_t size)
+{
+    return headerPutType(h, tag, RPM_STRING_ARRAY_TYPE, array, size);
+}
+
+int headerPutChar(Header h, rpmTag tag, char *val, rpm_count_t size)
+{
+    return headerPutType(h, tag, RPM_CHAR_TYPE, val, size);
+}
+
+int headerPutUint8(Header h, rpmTag tag, uint8_t *val, rpm_count_t size)
+{
+    return headerPutType(h, tag, RPM_INT8_TYPE, val, size);
+}
+
+int headerPutUint16(Header h, rpmTag tag, uint16_t *val, rpm_count_t size)
+{
+    return headerPutType(h, tag, RPM_INT16_TYPE, val, size);
+}
+
+int headerPutUint32(Header h, rpmTag tag, uint32_t *val, rpm_count_t size)
+{
+    return headerPutType(h, tag, RPM_INT32_TYPE, val, size);
+}
+
+int headerPutUint64(Header h, rpmTag tag, uint64_t *val, rpm_count_t size)
+{
+    return headerPutType(h, tag, RPM_INT64_TYPE, val, size);
+}
+
+int headerPutBin(Header h, rpmTag tag, uint8_t *val, rpm_count_t size)
+{
+    return headerPutType(h, tag, RPM_BIN_TYPE, val, size);
+}
+
 int headerAddI18NString(Header h, rpmTag tag, const char * string,
                const char * lang)
 {
index 8d7d853..bd0759e 100644 (file)
@@ -183,6 +183,39 @@ typedef enum headerPutFlags_e {
  */
 int headerPut(Header h, rpmtd td, headerPutFlags flags);
 
+/** \ingroup header 
+ * @{
+ * Type-safe methods for inserting tag data to header.
+ * Tag data type is validated to match the function type, ie things like
+ * headerPutUint32(h, RPMTAG_NAME, ...) will return failure. For non-array
+ * types size must equal 1, and data is checked to be non-NULL. For array
+ * types, add-or-append mode is always used.
+ *
+ * headerPutString() can be used on both RPM_STRING_TYPE and 
+ * RPM_STRING_ARRAY_TYPE (to add a single string into the array) tags,
+ * for others the type must match exactly.
+ *
+ * These are intended to "do the right thing" in the common case, if you 
+ * need more fine grained control use headerPut() & friends instead.
+ * @todo               Make doxygen group these meaningfully.
+ *
+ * @param h            header
+ * @param tag          tag to insert
+ * @param val          pointer to value(s)
+ * @param size         number of items in array (1 or larger)
+ * @return             1 on success, 0 on failure
+ * 
+ */
+int headerPutString(Header h, rpmTag tag, const char *str);
+int headerPutStringArray(Header h, rpmTag tag, const char **val, rpm_count_t size);
+int headerPutBin(Header h, rpmTag tag, uint8_t *val, rpm_count_t size);
+int headerPutChar(Header h, rpmTag tag, char *val, rpm_count_t size);
+int headerPutUint8(Header h, rpmTag tag, uint8_t *val, rpm_count_t size);
+int headerPutUint16(Header h, rpmTag tag, uint16_t *val, rpm_count_t size);
+int headerPutUint32(Header h, rpmTag tag, uint32_t *val, rpm_count_t size);
+int headerPutUint64(Header h, rpmTag tag, uint64_t *val, rpm_count_t size);
+/** @} */
+
 /** \ingroup header
  * Add locale specific tag to header.
  * A NULL lang is interpreted as the C locale. Here are the rules: