/* ===========================================================================
*
*                            PUBLIC DOMAIN NOTICE
*               National Center for Biotechnology Information
*
*  This software/database is a "United States Government Work" under the
*  terms of the United States Copyright Act.  It was written as part of
*  the author's official duties as a United States Government employee and
*  thus cannot be copyrighted.  This software/database is freely available
*  to the public for use. The National Library of Medicine and the U.S.
*  Government have not placed any restriction on its use or reproduction.
*
*  Although all reasonable efforts have been taken to ensure the accuracy
*  and reliability of the software and data, the NLM and the U.S.
*  Government do not and cannot warrant the performance or results that
*  may be obtained by using this software or data. The NLM and the U.S.
*  Government disclaim all warranties, express or implied, including
*  warranties of performance, merchantability or fitness for any particular
*  purpose.
*
*  Please cite the author in any work or product based on this material.
*
* ===========================================================================*/

#include <ncbi.h>
#include <dfa.h>

/***************************************************************************
*	dfa_contains(dp, pattern, patlen, patID)
*
*	Determine whether a given pattern/patID combination is accepted by
*	the DFA.  (This is kind of a mini-dfa_add()).  Only callable while
*	the DFA is in the operational state dfaOpstateOpen.
*
*	Return Values:  NULL if pattern was not found or bad letter in pattern,
*					dfa_patlist * if the pattern was found
***************************************************************************/
DFA_PatlistPtr _cdecl
dfa_contains(dp, pattern, patlen, patID)
	DFAPtr	dp;			/* the initialized DFA structure */
	unsigned char PNTR pattern;	/* the pattern to look for in the DFA */
	size_t	patlen;	/* length of the pattern (in DFA_Letters) */
	DFA_PatID	patID;		/* the associated patID */
{
	DFA_StatePtr	S;
#ifndef DFA_THENEED4SPEED
	int	patChr;
#endif
	DFA_AcceptPtr	A;
	DFA_PatlistPtr	P;
	int	i;
	DFA_StatePtr	state0;

#ifndef DFA_THENEED4SPEED
	if (dp == NULL || dp->magic != DFA_MAGIC) {
		dfaerrno = dfaErrBadPtr;
		return NULL;
	}
	if (dp->opstate != dfaOpstateOpen) {
		dfaerrno = dfaErrOpstate;
		return NULL;
	}
	if (patlen == 0) {
		dfaerrno = dfaErrPatlen;
		return NULL;
	}
#endif

	S = state0 = dp->state0;
	for (i=0; i<patlen-1; ++i) {
#ifndef DFA_THENEED4SPEED
		if ((patChr = *pattern++) < dp->amin || patChr > dp->amax)
			goto BadLetter;
		S = S->next[patChr];
#else
		S = S->next[*pattern++];
#endif
		if (S == state0)
			goto NotFound;
		if (!DFA_ISACCEPTING(S))
			continue;
		A = (DFA_AcceptPtr)DFA_UNMUNGED(S);
		S = A->retState;
		if (S == state0)
			goto NotFound;
	}

#ifndef DFA_THENEED4SPEED
	if ((patChr = *pattern) < dp->amin || patChr > dp->amax)
		goto BadLetter;
	if (!DFA_ISACCEPTING(S = S->next[patChr]))
		goto NotFound;
#else
	if (!DFA_ISACCEPTING(S = S->next[*pattern]))
		goto NotFound;
#endif

	A = (DFA_AcceptPtr)DFA_UNMUNGED(S);
	P = &A->pl;

	do
		if (memcmp((VoidPtr)&P->patID, (VoidPtr)&patID, sizeof(patID)) == 0)
			return (DFA_PatlistPtr)A; /* Found it! */
	while ((P = P->chain) != NULL);

NotFound:
	dfaerrno = dfaErrNotFound;
	return NULL;

#ifndef DFA_THENEED4SPEED
BadLetter:
	dfaerrno = dfaErrNonAlpha;
	return NULL;
#endif
}
