src/bloblist.c
author Volker Birk <vb@pep-project.org>
Fri, 28 Feb 2020 17:04:22 +0100
branchsync
changeset 4459 6e53c30bc023
parent 4327 efeb9e634e14
permissions -rw-r--r--
removing comment, which is not true any more
     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 *bloblist = NULL;
    85 
    86     // head
    87     char *blob2 = malloc(src->size);
    88     assert(blob2);
    89     if (blob2 == NULL)
    90         goto enomem;
    91 
    92     memcpy(blob2, src->value, src->size);
    93 
    94     bloblist = new_bloblist(blob2, src->size, src->mime_type, src->filename);
    95     if (bloblist == NULL)
    96         goto enomem;
    97     blob2 = NULL;
    98 
    99     bloblist_t* src_curr = src->next;
   100     bloblist_t** dst_curr_ptr = &bloblist->next;
   101 
   102     // list
   103     while (src_curr) {
   104         blob2 = malloc(src_curr->size);
   105 
   106         assert(blob2);
   107         if (blob2 == NULL)
   108             goto enomem;
   109 
   110         memcpy(blob2, src_curr->value, src_curr->size);
   111         *dst_curr_ptr = new_bloblist(blob2, src_curr->size, src_curr->mime_type, src_curr->filename);
   112         if (*dst_curr_ptr == NULL)
   113             goto enomem;
   114 
   115         src_curr = src_curr->next;
   116         dst_curr_ptr = &((*dst_curr_ptr)->next);
   117     }
   118 
   119     return bloblist;
   120 
   121 enomem:
   122     free(blob2);
   123     free_bloblist(bloblist);
   124     return NULL;
   125 }
   126 
   127 DYNAMIC_API bloblist_t *bloblist_add(bloblist_t *bloblist, char *blob, size_t size,
   128         const char *mime_type, const char *filename)
   129 {
   130     assert(blob);
   131     if (!blob)
   132         return NULL;
   133 
   134     if (!bloblist)
   135         return new_bloblist(blob, size, mime_type, filename);
   136 
   137     if (!bloblist->value) { // empty list
   138         assert(!bloblist->next);
   139         if (bloblist->next)
   140             return NULL; // invalid list
   141             
   142         if (!set_blob_data(bloblist, blob, size, mime_type, filename)) {
   143             free(bloblist);
   144             bloblist = NULL;
   145         }
   146 
   147         return bloblist;
   148     }
   149 
   150     bloblist_t* list_curr = bloblist;
   151     void (*release_value)(char *) = list_curr->release_value;
   152 
   153     while (list_curr->next)
   154         list_curr = list_curr->next;
   155 
   156     list_curr->next = new_bloblist(blob, size, mime_type, filename);
   157     list_curr->release_value = release_value;
   158 
   159     assert(list_curr->next);
   160     if (!list_curr->next)
   161         return NULL;
   162 
   163     return list_curr->next;
   164 }
   165 
   166 DYNAMIC_API bloblist_t* bloblist_join(bloblist_t* first, bloblist_t* second) {
   167     if (!first)
   168         return second;
   169     if (!second)
   170         return first;
   171     
   172     bloblist_t* list_curr = first;
   173     
   174     while (list_curr->next) {
   175         list_curr = list_curr->next;
   176     }
   177     list_curr->next = second;
   178     
   179     return first;
   180 }
   181 
   182 DYNAMIC_API int bloblist_length(const bloblist_t *bloblist)
   183 {
   184     int len = 0;
   185 
   186     for (const bloblist_t *_bl = bloblist; _bl && _bl->value; _bl = _bl->next)
   187         len++;
   188 
   189     return len;
   190 }
   191 
   192 DYNAMIC_API void set_blob_disposition(bloblist_t* blob, 
   193         content_disposition_type disposition)
   194 {
   195     if (blob)                                    
   196         blob->disposition = disposition;
   197 }