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