src/bloblist.c
author buff <andreas@pep-project.org>
Fri, 22 Jan 2021 12:26:53 +0100
branchIOSAD-186
changeset 5279 eef5d0a66d7d
parent 5192 4bd00a6b073f
child 5193 74e24f603e30
permissions -rw-r--r--
merge Release_2.1.11
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 #include <stdbool.h>
     5 #include <stdlib.h>
     6 #include <assert.h>
     7 #include <string.h>
     8 
     9 #include "platform.h"
    10 #include "bloblist.h"
    11 
    12 static bool set_blob_data(bloblist_t* bloblist, char* blob, size_t size, const char* mime_type,
    13         const char* filename)
    14 {
    15     if (!bloblist)
    16         return false;
    17         
    18     if (mime_type) {
    19        bloblist->mime_type = strdup(mime_type);
    20        if (bloblist->mime_type == NULL) {
    21            return false;
    22        }
    23     }
    24     
    25     if (filename) {
    26        bloblist->filename = strdup(filename);
    27        if (bloblist->filename == NULL) {
    28            free(bloblist->mime_type);
    29            return false;
    30        }
    31        /* Default behaviour, can be overwritten post-allocation with
    32           set_blob_content_disposition */
    33        if (strncmp(filename, "cid://", 6) == 0)
    34            bloblist->disposition = PEP_CONTENT_DISP_INLINE;
    35     }               
    36     
    37     if (blob) {
    38         bloblist->value = blob;
    39         bloblist->size = size;
    40     }
    41     
    42     return true;
    43 }
    44 
    45 DYNAMIC_API bloblist_t *new_bloblist(char *blob, size_t size, const char *mime_type,
    46         const char *filename)
    47 {
    48     bloblist_t * bloblist = calloc(1, sizeof(bloblist_t));
    49     assert(bloblist);
    50     if (bloblist == NULL)
    51         return NULL;
    52 
    53     if (!set_blob_data(bloblist, blob, size, mime_type, filename)) {
    54         free(bloblist);
    55         bloblist = NULL;
    56     }
    57 
    58     return bloblist;
    59 }
    60 
    61 DYNAMIC_API void free_bloblist(bloblist_t *bloblist)
    62 {
    63     bloblist_t *curr = bloblist;
    64 
    65     while (curr) {
    66         bloblist_t *next = curr->next;
    67         if (curr->release_value)
    68             curr->release_value(curr->value);
    69         else
    70             free(curr->value);
    71         free(curr->mime_type);
    72         free(curr->filename);
    73         free(curr);
    74         curr = next;
    75     }
    76 }
    77 
    78 DYNAMIC_API bloblist_t *bloblist_dup(const bloblist_t *src)
    79 {
    80     assert(src);
    81     if (src == NULL)
    82         return NULL;
    83 
    84     bloblist_t* head_ptr = NULL;
    85     bloblist_t** dst_curr_ptr = &head_ptr;
    86 
    87     const bloblist_t* src_curr = src;
    88 
    89     char* blob2 = NULL;
    90 
    91     for ( ; src_curr; src_curr = src_curr->next, dst_curr_ptr = &((*dst_curr_ptr)->next)) {
    92         blob2 = malloc(src_curr->size);
    93 
    94         assert(blob2);
    95         if (blob2 == NULL)
    96             goto enomem;
    97 
    98         // This is why we don't calloc
    99         memcpy(blob2, src_curr->value, src_curr->size);
   100 
   101         *dst_curr_ptr = new_bloblist(blob2, src_curr->size, src_curr->mime_type, src_curr->filename);
   102         if (*dst_curr_ptr == NULL)
   103             goto enomem;
   104     }
   105 
   106     if (!head_ptr)
   107         return NULL;
   108 
   109     return head_ptr;
   110 
   111 enomem:
   112     free(blob2);
   113     free_bloblist(head_ptr);
   114     return NULL;
   115 }
   116 
   117 DYNAMIC_API bloblist_t *bloblist_add(bloblist_t *bloblist, char *blob, size_t size,
   118         const char *mime_type, const char *filename)
   119 {
   120     assert(blob);
   121     if (!blob)
   122         return NULL;
   123 
   124     if (!bloblist)
   125         return new_bloblist(blob, size, mime_type, filename);
   126 
   127     if (!bloblist->value) { // empty list
   128         assert(!bloblist->next);
   129         if (bloblist->next)
   130             return NULL; // invalid list
   131             
   132         if (!set_blob_data(bloblist, blob, size, mime_type, filename)) {
   133             free(bloblist);
   134             bloblist = NULL;
   135         }
   136 
   137         return bloblist;
   138     }
   139 
   140     bloblist_t* list_curr = bloblist;
   141     void (*release_value)(char *) = list_curr->release_value;
   142 
   143     while (list_curr->next)
   144         list_curr = list_curr->next;
   145 
   146     list_curr->next = new_bloblist(blob, size, mime_type, filename);
   147     list_curr->next->release_value = release_value;
   148 
   149     assert(list_curr->next);
   150     if (!list_curr->next)
   151         return NULL;
   152 
   153     return list_curr->next;
   154 }
   155 
   156 DYNAMIC_API bloblist_t* bloblist_join(bloblist_t* first, bloblist_t* second) {
   157     if (!first)
   158         return second;
   159     if (!second)
   160         return first;
   161 
   162     if (first == second)
   163         return first;
   164 
   165     bloblist_t* list_curr = first;
   166     
   167     while (list_curr->next) {
   168         list_curr = list_curr->next;
   169     }
   170     list_curr->next = second;
   171     
   172     return first;
   173 }
   174 
   175 DYNAMIC_API int bloblist_length(const bloblist_t *bloblist)
   176 {
   177     int len = 0;
   178 
   179     for (const bloblist_t *_bl = bloblist; _bl && _bl->value; _bl = _bl->next)
   180         len++;
   181 
   182     return len;
   183 }
   184 
   185 DYNAMIC_API void set_blob_disposition(bloblist_t* blob, 
   186         content_disposition_type disposition)
   187 {
   188     if (blob)                                    
   189         blob->disposition = disposition;
   190 }