/*
 * $Header: /san01/cvs/ashpool/csrc/continuity/mecha/Attic/pat.c,v 1.6 2004/04/30 13:41:56 aleigh Exp $
 *
 * Copyright (c) 2004, Alex Leigh, All Rights Reserved
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH. The copyright
 * notice above does not evidence any actual or intended publication of
 * such source code.
 *
 * Use, disclosure, copying, distribution, or transmission of this code without
 * express permission is prohibited.
 */

#include "mecha.h"

struct patSstack {
    struct patSpattern *patterns;
    size_t count;
    void (*destructor) (void *);
};

/* Some other time we will extend this to include the per-compiled version of the
 * regular expression for performance reasons, but I've got other fish to fry
 * right now. -aleigh
 */
struct patSpattern {
    const char *regexp;
    void *target;
};
typedef struct patSpattern patTpattern;

/* This may need to take a destructor if we say that the list is going to be
 * responsible for freeing the void pointers passed into it. -aleigh
 */

/*
 * MT - Does not require a lock.
 */
patTstack *patFstack_init(void (*destructor) (void *))
{
    patTstack *stack = (patTstack *) malloc(sizeof(patTstack));

    assert(stack != NULL);

    memFclear(stack, sizeof(patTstack));

    stack->destructor = destructor;

    return stack;
}

/*
 * MT - Requires a write lock.
 * */
void patFstack_free(patTstack * stack)
{
    size_t i;

    for (i = 0; i < stack->count; i++) {
        if (stack->destructor != NULL) {
            (stack->destructor)(stack->patterns[i].target);
        }
        free((void *)stack->patterns[i].regexp);        /* We added this field with strFcopy() */
    }

    free(stack->patterns);
    free(stack);
}

/*
 * MT - Does not require a lock.
 */
size_t patFstack_size(patTstack * stack)
{
    return stack->count;
}

/*
 * MT - Requires a write lock on the stack.
 */
void patFstack_append(patTstack * stack, const char *regexp, void *target)
{
    assert(stack != NULL);
    assert(regexp != NULL);
    assert(target != NULL);

    if (stack->count == 0) {
        stack->patterns = (patTpattern *) malloc(sizeof(patTpattern));
        stack->patterns[0].regexp = strFcopy(regexp);
        stack->patterns[0].target = target;
        stack->count = 1;
    } else {
        stack->count++;
        stack->patterns =
            (patTpattern *) realloc(stack->patterns,
                                    sizeof(patTpattern) * stack->count);
        stack->patterns[stack->count].regexp = strFcopy(regexp);
        stack->patterns[stack->count].target = target;
    }
}

/*
 * MT - requires at least a read lock on the stack. Patterns are searched in the order
 * that they were appended into the stack.
 */
void *patFstack_search(patTstack * stack, const char *needle)
{
    size_t i;

    assert(stack != NULL);
    assert(needle != NULL);

    for(i=0;i<stack->count;i++) {
        if(expFmatch(stack->patterns[i].regexp, needle)==1) {
            logFmsg(3,"pat: Matched.");
            return stack->patterns[i].target;
        }
    }
    return NULL;
}
