/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * CMS array functions.
 */

#include "cmslocal.h"

#include "secerr.h"

/*
 * ARRAY FUNCTIONS
 *
 * In NSS, arrays are rather primitive arrays of pointers.
 * Makes it easy to walk the array, but hard to count elements
 * and manage the storage.
 *
 * This is a feeble attempt to encapsulate the functionality
 * and get rid of hundreds of lines of similar code
 */

/*
 * NSS_CMSArray_Alloc - allocate an array in an arena
 *
 * This allocates space for the array of pointers
 */
void **
NSS_CMSArray_Alloc(PLArenaPool *poolp, int n)
{
    return (void **)PORT_ArenaZAlloc(poolp, n * sizeof(void *));
}

/*
 * NSS_CMSArray_Add - add an element to the end of an array
 *
 * The array of pointers is either created (if array was empty before) or grown.
 */
SECStatus
NSS_CMSArray_Add(PLArenaPool *poolp, void ***array, void *obj)
{
    void **p;
    int n;
    void **dest;

    PORT_Assert(array != NULL);
    if (array == NULL)
        return SECFailure;

    if (*array == NULL) {
        dest = (void **)PORT_ArenaAlloc(poolp, 2 * sizeof(void *));
        n = 0;
    } else {
        n = 0;
        p = *array;
        while (*p++)
            n++;
        dest = (void **)PORT_ArenaGrow(poolp,
                                       *array,
                                       (n + 1) * sizeof(void *),
                                       (n + 2) * sizeof(void *));
    }

    if (dest == NULL)
        return SECFailure;

    dest[n] = obj;
    dest[n + 1] = NULL;
    *array = dest;
    return SECSuccess;
}

/*
 * NSS_CMSArray_IsEmpty - check if array is empty
 */
PRBool
NSS_CMSArray_IsEmpty(void **array)
{
    return (array == NULL || array[0] == NULL);
}

/*
 * NSS_CMSArray_Count - count number of elements in array
 */
int
NSS_CMSArray_Count(void **array)
{
    int n = 0;

    if (array == NULL)
        return 0;

    while (*array++ != NULL)
        n++;

    return n;
}

/*
 * NSS_CMSArray_Sort - sort an array in place
 *
 * If "secondary" or "tertiary are not NULL, it must be arrays with the same
 *  number of elements as "primary". The same reordering will get applied to it.
 *
 * "compare" is a function that returns
 *  < 0 when the first element is less than the second
 *  = 0 when the first element is equal to the second
 *  > 0 when the first element is greater than the second
 * to acheive ascending ordering.
 */
void
NSS_CMSArray_Sort(void **primary, int (*compare)(void *, void *), void **secondary, void **tertiary)
{
    int n, i, limit, lastxchg;
    void *tmp;

    n = NSS_CMSArray_Count(primary);

    PORT_Assert(secondary == NULL || NSS_CMSArray_Count(secondary) == n);
    PORT_Assert(tertiary == NULL || NSS_CMSArray_Count(tertiary) == n);

    if (n <= 1) /* ordering is fine */
        return;

    /* yes, ladies and gentlemen, it's BUBBLE SORT TIME! */
    limit = n - 1;
    while (1) {
        lastxchg = 0;
        for (i = 0; i < limit; i++) {
            if ((*compare)(primary[i], primary[i + 1]) > 0) {
                /* exchange the neighbours */
                tmp = primary[i + 1];
                primary[i + 1] = primary[i];
                primary[i] = tmp;
                if (secondary) {            /* secondary array? */
                    tmp = secondary[i + 1]; /* exchange there as well */
                    secondary[i + 1] = secondary[i];
                    secondary[i] = tmp;
                }
                if (tertiary) {            /* tertiary array? */
                    tmp = tertiary[i + 1]; /* exchange there as well */
                    tertiary[i + 1] = tertiary[i];
                    tertiary[i] = tmp;
                }
                lastxchg = i + 1; /* index of the last element bubbled up */
            }
        }
        if (lastxchg == 0) /* no exchanges, so array is sorted */
            break;         /* we're done */
        limit = lastxchg;  /* array is sorted up to [limit] */
    }
}

#if 0

/* array iterator stuff... not used */

typedef void **NSSCMSArrayIterator;

/* iterator */
NSSCMSArrayIterator
NSS_CMSArray_First(void **array)
{
    if (array == NULL || array[0] == NULL)
    return NULL;
    return (NSSCMSArrayIterator)&(array[0]);
}

void *
NSS_CMSArray_Obj(NSSCMSArrayIterator iter)
{
    void **p = (void **)iter;

    return *iter;   /* which is NULL if we are at the end of the array */
}

NSSCMSArrayIterator
NSS_CMSArray_Next(NSSCMSArrayIterator iter)
{
    void **p = (void **)iter;

    return (NSSCMSArrayIterator)(p + 1);
}

#endif
