tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cmsarray.c (4688B)


      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 * CMS array functions.
      7 */
      8 
      9 #include "cmslocal.h"
     10 
     11 #include "secerr.h"
     12 
     13 /*
     14 * ARRAY FUNCTIONS
     15 *
     16 * In NSS, arrays are rather primitive arrays of pointers.
     17 * Makes it easy to walk the array, but hard to count elements
     18 * and manage the storage.
     19 *
     20 * This is a feeble attempt to encapsulate the functionality
     21 * and get rid of hundreds of lines of similar code
     22 */
     23 
     24 /*
     25 * NSS_CMSArray_Alloc - allocate an array in an arena
     26 *
     27 * This allocates space for the array of pointers
     28 */
     29 void **
     30 NSS_CMSArray_Alloc(PLArenaPool *poolp, int n)
     31 {
     32    return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *));
     33 }
     34 
     35 /*
     36 * NSS_CMSArray_Add - add an element to the end of an array
     37 *
     38 * The array of pointers is either created (if array was empty before) or grown.
     39 */
     40 SECStatus
     41 NSS_CMSArray_Add(PLArenaPool *poolp, void ***array, void *obj)
     42 {
     43    void **p;
     44    int n;
     45    void **dest;
     46 
     47    PORT_Assert(array != NULL);
     48    if (array == NULL)
     49        return SECFailure;
     50 
     51    if (*array == NULL) {
     52        dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *));
     53        n = 0;
     54    } else {
     55        n = 0;
     56        p = *array;
     57        while (*p++)
     58            n++;
     59        dest = (void **)PORT_ArenaGrow(poolp,
     60                                       *array,
     61                                       (n + 1) * sizeof(void *),
     62                                       (n + 2) * sizeof(void *));
     63    }
     64 
     65    if (dest == NULL)
     66        return SECFailure;
     67 
     68    dest[n] = obj;
     69    dest[n + 1] = NULL;
     70    *array = dest;
     71    return SECSuccess;
     72 }
     73 
     74 /*
     75 * NSS_CMSArray_IsEmpty - check if array is empty
     76 */
     77 PRBool
     78 NSS_CMSArray_IsEmpty(void **array)
     79 {
     80    return (array == NULL || array[0] == NULL);
     81 }
     82 
     83 /*
     84 * NSS_CMSArray_Count - count number of elements in array
     85 */
     86 int
     87 NSS_CMSArray_Count(void **array)
     88 {
     89    int n = 0;
     90 
     91    if (array == NULL)
     92        return 0;
     93 
     94    while (*array++ != NULL)
     95        n++;
     96 
     97    return n;
     98 }
     99 
    100 /*
    101 * NSS_CMSArray_Sort - sort an array in place
    102 *
    103 * If "secondary" or "tertiary are not NULL, it must be arrays with the same
    104 *  number of elements as "primary". The same reordering will get applied to it.
    105 *
    106 * "compare" is a function that returns
    107 *  < 0 when the first element is less than the second
    108 *  = 0 when the first element is equal to the second
    109 *  > 0 when the first element is greater than the second
    110 * to acheive ascending ordering.
    111 */
    112 void
    113 NSS_CMSArray_Sort(void **primary, int (*compare)(void *, void *), void **secondary, void **tertiary)
    114 {
    115    int n, i, limit, lastxchg;
    116    void *tmp;
    117 
    118    n = NSS_CMSArray_Count(primary);
    119 
    120    PORT_Assert(secondary == NULL || NSS_CMSArray_Count(secondary) == n);
    121    PORT_Assert(tertiary == NULL || NSS_CMSArray_Count(tertiary) == n);
    122 
    123    if (n <= 1) /* ordering is fine */
    124        return;
    125 
    126    /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */
    127    limit = n - 1;
    128    while (1) {
    129        lastxchg = 0;
    130        for (i = 0; i < limit; i++) {
    131            if ((*compare)(primary[i], primary[i + 1]) > 0) {
    132                /* exchange the neighbours */
    133                tmp = primary[i + 1];
    134                primary[i + 1] = primary[i];
    135                primary[i] = tmp;
    136                if (secondary) {            /* secondary array? */
    137                    tmp = secondary[i + 1]; /* exchange there as well */
    138                    secondary[i + 1] = secondary[i];
    139                    secondary[i] = tmp;
    140                }
    141                if (tertiary) {            /* tertiary array? */
    142                    tmp = tertiary[i + 1]; /* exchange there as well */
    143                    tertiary[i + 1] = tertiary[i];
    144                    tertiary[i] = tmp;
    145                }
    146                lastxchg = i + 1; /* index of the last element bubbled up */
    147            }
    148        }
    149        if (lastxchg == 0) /* no exchanges, so array is sorted */
    150            break;         /* we're done */
    151        limit = lastxchg;  /* array is sorted up to [limit] */
    152    }
    153 }
    154 
    155 #if 0
    156 
    157 /* array iterator stuff... not used */
    158 
    159 typedef void **NSSCMSArrayIterator;
    160 
    161 /* iterator */
    162 NSSCMSArrayIterator
    163 NSS_CMSArray_First(void **array)
    164 {
    165    if (array == NULL || array[0] == NULL)
    166    return NULL;
    167    return (NSSCMSArrayIterator)&(array[0]);
    168 }
    169 
    170 void *
    171 NSS_CMSArray_Obj(NSSCMSArrayIterator iter)
    172 {
    173    void **p = (void **)iter;
    174 
    175    return *iter;   /* which is NULL if we are at the end of the array */
    176 }
    177 
    178 NSSCMSArrayIterator
    179 NSS_CMSArray_Next(NSSCMSArrayIterator iter)
    180 {
    181    void **p = (void **)iter;
    182 
    183    return (NSSCMSArrayIterator)(p + 1);
    184 }
    185 
    186 #endif