Add a type + basic api for bundle of digests (on same data)
authorPanu Matilainen <pmatilai@redhat.com>
Wed, 25 Mar 2009 11:08:09 +0000 (13:08 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Wed, 25 Mar 2009 11:08:09 +0000 (13:08 +0200)
- in various places we need to calculate different digests of the same
  data, having them stored in a single container makes managing easier
- can hold as many digest types as we support
- remembers how much input data it has handled

rpmio/digest.c
rpmio/rpmpgp.h

index 09002d8..707d6e0 100644 (file)
@@ -24,6 +24,91 @@ struct DIGEST_CTX_s {
     pgpHashAlgo algo;          /*!< Used hash algorithm */
 };
 
+#define DIGESTS_MAX 11
+struct rpmDigestBundle_s {
+    int index_min;                     /*!< Smallest index of active digest */
+    int index_max;                     /*!< Largest index of active digest */
+    off_t nbytes;                      /*!< Length of total input data */
+    DIGEST_CTX digests[DIGESTS_MAX];   /*!< Digest contexts indexed by algo */
+};
+
+rpmDigestBundle rpmDigestBundleNew(void)
+{
+    rpmDigestBundle bundle = xcalloc(1, sizeof(*bundle));
+    return bundle;
+}
+
+rpmDigestBundle rpmDigestBundleFree(rpmDigestBundle bundle)
+{
+    if (bundle) {
+       for (int i = bundle->index_min; i <= bundle->index_max ; i++) {
+           if (bundle->digests[i] == NULL)
+               continue;
+           rpmDigestFinal(bundle->digests[i], NULL, NULL, 0);
+           bundle->digests[i] = NULL;
+       }
+       memset(bundle, 0, sizeof(*bundle));
+       free(bundle);
+    }
+    return NULL;
+}
+
+int rpmDigestBundleAdd(rpmDigestBundle bundle, pgpHashAlgo algo,
+                       rpmDigestFlags flags)
+{
+    DIGEST_CTX ctx = NULL;
+    if (bundle && algo > 0 && algo < DIGESTS_MAX) {
+       if (bundle->digests[algo] == NULL) {
+           ctx = rpmDigestInit(algo, flags);
+           if (ctx) {
+               bundle->digests[algo] = ctx;
+               if (algo < bundle->index_min) {
+                   bundle->index_min = algo;
+               }
+               if (algo > bundle->index_max) {
+                   bundle->index_max = algo;
+               }
+           }
+       }
+    }
+    return (ctx != NULL);
+}
+
+int rpmDigestBundleUpdate(rpmDigestBundle bundle, const void *data, size_t len)
+{
+    int rc = 0;
+    if (bundle && data && len > 0) {
+       for (int i = bundle->index_min; i <= bundle->index_max; i++) {
+           DIGEST_CTX ctx = bundle->digests[i];
+           if (ctx == NULL)
+               continue;
+           rc += rpmDigestUpdate(ctx, data, len);
+       }
+       bundle->nbytes += len;
+    }
+    return rc;
+}
+
+int rpmDigestBundleFinal(rpmDigestBundle bundle, 
+               pgpHashAlgo algo, void ** datap, size_t * lenp, int asAscii)
+{
+    int rc = 0;
+    if (bundle && algo >= bundle->index_min && algo <= bundle->index_max) {
+       rc = rpmDigestFinal(bundle->digests[algo], datap, lenp, asAscii);
+       bundle->digests[algo] = NULL;
+    }
+    return rc;
+}
+
+DIGEST_CTX rpmDigestBundleDupCtx(rpmDigestBundle bundle, pgpHashAlgo algo)
+{
+    DIGEST_CTX dup = NULL;
+    if (bundle && algo >= bundle->index_min && algo <= bundle->index_max) {
+       dup = rpmDigestDup(bundle->digests[algo]);
+    }
+    return dup;
+}
+
 DIGEST_CTX
 rpmDigestDup(DIGEST_CTX octx)
 {
index bdc883b..c3d6097 100644 (file)
@@ -23,6 +23,7 @@ extern "C" {
 /** \ingroup rpmpgp
  */
 typedef struct DIGEST_CTX_s * DIGEST_CTX;
+typedef struct rpmDigestBundle_s * rpmDigestBundle;
 
 /** \ingroup rpmpgp
  */
@@ -1100,6 +1101,59 @@ int rpmDigestFinal(DIGEST_CTX ctx,
        void ** datap,
        size_t * lenp, int asAscii);
 
+/** \ingroup rpmpgp
+ * Create a new digest bundle.
+ * @return             New digest bundle
+ */
+rpmDigestBundle rpmDigestBundleNew(void);
+
+/** \ingroup rpmpgp
+ * Free a digest bundle and all contained digest contexts.
+ * @param bundle       digest bundle
+ * @return             NULL always
+ */
+rpmDigestBundle rpmDigestBundleFree(rpmDigestBundle bundle);
+
+/** \ingroup rpmpgp
+ * Add a new type of digest to a bundle.
+ * @param bundle       digest bundle
+ * @param algo         type of digest
+ * @param flags                bit(s) to control digest operation
+ * @return             0 on success
+ */
+int rpmDigestBundleAdd(rpmDigestBundle bundle, pgpHashAlgo algo,
+                       rpmDigestFlags flags);
+
+/** \ingroup rpmpgp
+ * Update contexts within bundle with next plain text buffer.
+ * @param bundle       digest bundle
+ * @param data         next data buffer
+ * @param len          no. bytes of data
+ * @return             0 on success
+ */
+int rpmDigestBundleUpdate(rpmDigestBundle bundle, const void *data, size_t len);
+
+/** \ingroup rpmpgp
+ * Return digest from a bundle and destroy context, see rpmDigestFinal().
+ *
+ * @param bundle       digest bundle
+ * @param algo         type of digest to return
+ * @retval datap       address of returned digest
+ * @retval lenp                address of digest length
+ * @param asAscii      return digest as ascii string?
+ * @return             0 on success
+ */
+int rpmDigestBundleFinal(rpmDigestBundle bundle,
+        pgpHashAlgo algo, void ** datap, size_t * lenp, int asAscii);
+
+/** \ingroup rpmpgp
+ * Duplicate a digest context from a bundle.
+ * @param bundle       digest bundle
+ * @param algo         type of digest to dup
+ * @return             duplicated digest context
+ */
+DIGEST_CTX rpmDigestBundleDupCtx(rpmDigestBundle bundle, pgpHashAlgo algo);
+
 #ifdef __cplusplus
 }
 #endif