Home | History | Annotate | Download | only in bodge
      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2  * License, v. 2.0. If a copy of the MPL was not distributed with this
      3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /*
      6  * Support routines for SECItemArray data structure.
      7  */
      8 
      9 #include "nssutil.h"
     10 #include "seccomon.h"
     11 #include "secitem.h"
     12 #include "secerr.h"
     13 #include "secport.h"
     14 
     15 #define NSSUTIL_VERSION_NUM \
     16     (NSSUTIL_VMAJOR * 10000 + NSSUTIL_VMINOR * 100 + NSSUTIL_VPATCH)
     17 #if NSSUTIL_VERSION_NUM < 31500
     18 // Added in NSS 3.15.
     19 typedef struct SECItemArrayStr SECItemArray;
     20 
     21 struct SECItemArrayStr {
     22     SECItem *items;
     23     unsigned int len;
     24 };
     25 #endif
     26 
     27 SECItemArray *
     28 SECITEM_AllocArray(PLArenaPool *arena, SECItemArray *array, unsigned int len)
     29 {
     30     SECItemArray *result = NULL;
     31     void *mark = NULL;
     32 
     33     if (arena != NULL) {
     34         mark = PORT_ArenaMark(arena);
     35     }
     36 
     37     if (array == NULL) {
     38         if (arena != NULL) {
     39             result = PORT_ArenaZAlloc(arena, sizeof(SECItemArray));
     40         } else {
     41             result = PORT_ZAlloc(sizeof(SECItemArray));
     42         }
     43         if (result == NULL) {
     44             goto loser;
     45         }
     46     } else {
     47         PORT_Assert(array->items == NULL);
     48         result = array;
     49     }
     50 
     51     result->len = len;
     52     if (len) {
     53         if (arena != NULL) {
     54             result->items = PORT_ArenaZNewArray(arena, SECItem, len);
     55         } else {
     56             result->items = PORT_ZNewArray(SECItem, len);
     57         }
     58         if (result->items == NULL) {
     59             goto loser;
     60         }
     61     } else {
     62         result->items = NULL;
     63     }
     64 
     65     if (mark) {
     66         PORT_ArenaUnmark(arena, mark);
     67     }
     68     return(result);
     69 
     70 loser:
     71     if ( arena != NULL ) {
     72         if (mark) {
     73             PORT_ArenaRelease(arena, mark);
     74         }
     75         if (array != NULL) {
     76             array->items = NULL;
     77             array->len = 0;
     78         }
     79     } else {
     80         if (result != NULL && array == NULL) {
     81             PORT_Free(result);
     82         }
     83         /*
     84          * If array is not NULL, the above has set array->data and
     85          * array->len to 0.
     86          */
     87     }
     88     return(NULL);
     89 }
     90 
     91 static void
     92 secitem_FreeArray(SECItemArray *array, PRBool zero_items, PRBool freeit)
     93 {
     94     unsigned int i;
     95 
     96     if (!array || !array->len || !array->items)
     97         return;
     98 
     99     for (i=0; i<array->len; ++i) {
    100         SECItem *item = &array->items[i];
    101 
    102         if (item->data) {
    103             if (zero_items) {
    104                 SECITEM_ZfreeItem(item, PR_FALSE);
    105             } else {
    106                 SECITEM_FreeItem(item, PR_FALSE);
    107             }
    108         }
    109     }
    110     PORT_Free(array->items);
    111     array->items = NULL;
    112     array->len = 0;
    113 
    114     if (freeit)
    115         PORT_Free(array);
    116 }
    117 
    118 void SECITEM_FreeArray(SECItemArray *array, PRBool freeit)
    119 {
    120     secitem_FreeArray(array, PR_FALSE, freeit);
    121 }
    122 
    123 void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit)
    124 {
    125     secitem_FreeArray(array, PR_TRUE, freeit);
    126 }
    127 
    128 SECItemArray *
    129 SECITEM_DupArray(PLArenaPool *arena, const SECItemArray *from)
    130 {
    131     SECItemArray *result;
    132     unsigned int i;
    133 
    134     if (!from || !from->items || !from->len)
    135         return NULL;
    136 
    137     result = SECITEM_AllocArray(arena, NULL, from->len);
    138     if (!result)
    139         return NULL;
    140 
    141     for (i=0; i<from->len; ++i) {
    142         SECStatus rv = SECITEM_CopyItem(arena,
    143                                         &result->items[i], &from->items[i]);
    144         if (rv != SECSuccess) {
    145             SECITEM_ZfreeArray(result, PR_TRUE);
    146             return NULL;
    147         }
    148     }
    149 
    150     return result;
    151 }
    152