Files
Clifford Yapp d824fc0c4e Keep longer directory names
We want to be consistent with the previous layout, to avoid needlessly
breaking existing codes.  The header update means client codes are not
required to include all of the stepcode library includes explicitly -
i.e., stepcode itself does not force this requirement with its own
internal includes.  However, if client codes do not want to add the
library prefixes to their own includes as we have for stepcode, they
should still be able to add the various includes and work as before.
Adjust the include directory names accordingly.
2022-10-02 17:57:57 -04:00

425 lines
14 KiB
C++

#ifndef COMPLEXSUP_H
#define COMPLEXSUP_H
/*****************************************************************************
* complexSupport.h *
* *
* Description: Slightly simplified version of exp2cxx's complexSupport.h.*
* This version works with the SCL and is used to validate *
* complex entities (user requests to build them). It does not *
* contain info for building these structures from a fedex *
* Express object, as the exp2cxx version. *
* *
* Created by: David Rosenfeld *
* Date: 5/9/97 *
*****************************************************************************/
#include <sc_export.h>
#include <iostream>
#include <fstream>
using namespace std;
#include "clutils/Str.h"
#define LISTEND 999
/** \def LISTEND
* signifies that an OrList has gone beyond its last viable choice
* among its children. FIXME is 999 high enough? Maybe use -1?
*/
enum MarkType {
NOMARK, ORMARK, MARK
};
/** \enum MarkType
// MARK is the usual value we'd mark with. If we mark with ORMARK, it means
// an OrList marked this node, so we'll know it may become unmarked later if
// we try another choice.
*/
enum MatchType {
UNKNOWN, UNSATISFIED, SATISFIED, MATCHSOME, MATCHALL, NEWCHOICE, NOMORE
};
/** \enum MatchType
// These are the conditions the EntList::match() functions may return. They
// are also the assigned values to EntList::viable.
//
// UNKNOWN - The default EntList::viable value - before any matching
// has been attempted.
// UNSATISFIED - EntList had conditions that EntNode did not satisfy (e.g.,
// EntList specified A AND B while EntNode only contained an
// A).
// SATISFIED - EntList had no conditions EntNode did not meet. But,
// EntList did not match (mark) any nodes of EntNode which
// were not already matched.
// MATCHSOME - EntList matched some of the nodes in EntNode.
// MATCHALL - EntList matched all the nodes in EntNode (complex entity
// can be instantiated).
// MORECHOICES - Special case - when trying alternate OR paths, this return
// value signifies that we have found another choice.
// NOMORE - Special case - when trying alternate OR paths, this return
// value signifies that no more alternates within this path.
*/
enum JoinType {
SIMPLE, AND, OR, ANDOR
};
class SimpleList;
class MultList;
class JoinList;
class AndOrList;
class AndList;
class OrList;
class ComplexList;
class ComplexCollect;
class SC_CORE_EXPORT EntNode {
friend class SimpleList;
friend class AndOrList;
friend class AndList;
friend class OrList;
friend class ComplexList;
public:
EntNode( const char * nm = "" ) : next( 0 ), mark( NOMARK ), multSupers( 0 ) {
StrToLower( nm, name );
}
EntNode( const char ** ); ///< given a list, create a linked list of EntNodes
~EntNode() {
if( next ) {
delete next;
}
}
operator const char * () {
return name;
}
bool operator== ( EntNode & ent ) {
return ( strcmp( name, ent.name ) == 0 );
}
bool operator< ( EntNode & ent ) {
return ( strcmp( name, ent.name ) < 0 );
}
bool operator> ( EntNode & ent ) {
return ( strcmp( name, ent.name ) > 0 );
}
EntNode & operator= ( EntNode & ent );
void Name( const char * nm ) {
strncpy( name, nm, BUFSIZ - 1 );
}
const char * Name() {
return name;
}
void setmark( MarkType stamp = MARK ) {
mark = stamp;
}
void markAll( MarkType = MARK );
void unmarkAll() {
markAll( NOMARK );
}
bool marked( MarkType base = ORMARK ) {
return ( mark >= base );
}
bool allMarked(); ///< returns true if all nodes in list are marked
int unmarkedCount();
bool multSuprs() {
return multSupers;
}
void multSuprs( int j ) {
multSupers = j;
}
void sort( EntNode ** );
EntNode * next;
private:
MarkType mark;
char name[BUFSIZ+1];
bool multSupers; ///< do I correspond to an entity with >1 supertype?
EntNode * lastSmaller( EntNode * ); ///< used by ::sort()
};
class SC_CORE_EXPORT EntList {
friend class MultList;
friend class JoinList;
friend class OrList;
friend class ComplexList;
friend class ComplexCollect;
friend ostream & operator<< ( ostream &, EntList & );
friend ostream & operator<< ( ostream &, MultList & );
public:
EntList( JoinType j ) : join( j ), next( 0 ), prev( 0 ), viable( UNKNOWN ),
level( 0 ) {}
virtual ~EntList() {}
MatchType viableVal() {
return viable;
}
virtual void setLevel( int l ) {
level = l;
}
virtual bool contains( char * ) = 0;
virtual bool hit( char * ) = 0;
virtual MatchType matchNonORs( EntNode * ) {
return UNKNOWN;
}
virtual bool acceptChoice( EntNode * ) = 0;
virtual void unmarkAll( EntNode * ) = 0;
virtual void reset() {
viable = UNKNOWN;
}
int siblings();
// List access functions. They access desired children based on their
// join or viable values. Below is an incomplete list of possible fns,
// but all we need.
EntList * firstNot( JoinType );
EntList * nextNot( JoinType j ) {
return ( next ) ? next->firstNot( j ) : NULL;
}
EntList * firstWanted( MatchType );
EntList * nextWanted( MatchType mat ) {
return ( next ) ? next->firstWanted( mat ) : NULL;
}
EntList * lastNot( JoinType );
EntList * prevNot( JoinType j ) {
return ( prev ) ? prev->lastNot( j ) : NULL;
}
EntList * lastWanted( MatchType );
EntList * prevWanted( MatchType mat ) {
return ( prev ) ? prev->lastWanted( mat ) : NULL;
}
JoinType join;
int multiple() {
return ( join != SIMPLE );
}
EntList * next = NULL;
EntList * prev = NULL;
protected:
MatchType viable;
/** \var viable
* How does this EntList match the complex type. Used especially if Ent-
* List's parent is an OrList or AndOrList to record if this child is an
* acceptable choice or not. For an AndOr, viable children are accepted
* right away. For Or, only one is accepted, but we keep track of the
* other possible solutions in case we'll want to try them.
*/
int level; ///< How many levels deep are we (main use for printing).
};
class SC_CORE_EXPORT SimpleList : public EntList {
friend class ComplexList;
friend ostream & operator<< ( ostream &, SimpleList & );
public:
SimpleList( const char * n ) : EntList( SIMPLE ), I_marked( NOMARK ) {
strncpy( name, n, sizeof( name ) - 1 );
name[sizeof( name ) - 1] = '\0'; /* sanity */
}
~SimpleList() {}
int operator== ( const char * nm ) {
return ( strcmp( name, nm ) == 0 );
}
const char * Name() {
return name;
}
bool contains( char * nm ) {
return *this == nm;
}
bool hit( char * nm ) {
return *this == nm;
}
MatchType matchNonORs( EntNode * );
bool acceptChoice( EntNode * );
void unmarkAll( EntNode * );
void reset() {
viable = UNKNOWN;
I_marked = NOMARK;
}
private:
char name[BUFSIZ+1]; ///< Name of entity we correspond to.
MarkType I_marked; ///< Did I mark, and with what type of mark.
};
/** \class MultList
* Supports concepts and functionality common to all the compound list
* types, especially AND and ANDOR.
*/
class SC_CORE_EXPORT MultList : public EntList {
friend class ComplexList;
friend class ComplexCollect;
friend ostream & operator<< ( ostream &, MultList & );
public:
MultList( JoinType j ) : EntList( j ), supertype( 0 ), numchildren( 0 ),
childList( 0 ) {}
~MultList();
void setLevel( int );
bool contains( char * );
bool hit( char * );
void appendList( EntList * );
EntList * copyList( EntList * );
virtual MatchType matchORs( EntNode * ) = 0;
virtual MatchType tryNext( EntNode * );
int childCount() {
return numchildren;
}
// EntList *operator[]( int );
EntList * getChild( int );
EntList * getLast() {
return ( getChild( numchildren - 1 ) );
}
void unmarkAll( EntNode * );
bool prevKnown( EntList * );
void reset();
protected:
int supertype; ///< do I represent a supertype?
int numchildren;
EntList * childList;
/** \var childList
* Points to a list of "children" of this EntList. E.g., if join =
* AND, it would point to a list of the entity types we are AND'ing.
* The children may be SIMPLE EntLists (contain entity names) or may
* themselves be And-, Or-, or AndOrLists.
*/
};
/** \class JoinList
* A specialized MultList, super for subtypes AndOrList and AndList, or
* ones which join their multiple children.
*/
class SC_CORE_EXPORT JoinList : public MultList {
public:
JoinList( JoinType j ) : MultList( j ) {}
~JoinList() {}
void setViableVal( EntNode * );
bool acceptChoice( EntNode * );
};
class SC_CORE_EXPORT AndOrList : public JoinList {
friend class ComplexList;
public:
AndOrList() : JoinList( ANDOR ) {}
~AndOrList() {}
MatchType matchNonORs( EntNode * );
MatchType matchORs( EntNode * );
};
class SC_CORE_EXPORT AndList : public JoinList {
friend class ComplexList;
friend ostream & operator<< ( ostream &, ComplexList & );
public:
AndList() : JoinList( AND ) {}
~AndList() {}
MatchType matchNonORs( EntNode * );
MatchType matchORs( EntNode * );
};
class SC_CORE_EXPORT OrList : public MultList {
public:
OrList() : MultList( OR ), choice( -1 ), choice1( -1 ), choiceCount( 0 ) {}
~OrList() {}
bool hit( char * );
MatchType matchORs( EntNode * );
MatchType tryNext( EntNode * );
void unmarkAll( EntNode * );
bool acceptChoice( EntNode * );
bool acceptNextChoice( EntNode * ents ) {
choice++;
return ( acceptChoice( ents ) );
}
void reset() {
choice = -1;
choice1 = -2;
choiceCount = 0;
MultList::reset();
}
private:
int choice; ///< Which choice of our childList did we select from this OrList
int choice1; ///< what's the first viable choice
int choiceCount; ///< how many choices are there entirely.
};
/** \class ComplexList
* Contains the entire list of EntLists which describe the set of
* instantiable complex entities defined by an EXPRESS expression.
*/
class SC_CORE_EXPORT ComplexList {
friend class ultList;
friend class ComplexCollect;
friend ostream & operator<< ( ostream &, ComplexList & );
public:
ComplexList( AndList * alist = NULL ) : list( 0 ), head( alist ), next( 0 ),
abstract( 0 ), dependent( 0 ),
multSupers( 0 ) {}
~ComplexList();
void buildList();
void remove();
int operator< ( ComplexList & c ) {
return ( strcmp( supertype(), c.supertype() ) < 0 );
}
int operator< ( char * name ) {
return ( strcmp( supertype(), name ) < 0 );
}
int operator== ( char * name ) {
return ( strcmp( supertype(), name ) == 0 );
}
const char * supertype() {
return ( dynamic_cast< SimpleList * >(head->childList ))->name ;
}
/** \fn supertype
* Based on knowledge that ComplexList always created by ANDing supertype
* with subtypes.
*/
bool toplevel( const char * );
bool contains( EntNode * );
bool matches( EntNode * );
EntNode * list; /**< List of all entities contained in this complex type,
* regardless of how. (Used as a quick way of determining
* if this List *may* contain a certain complex type.)
*/
AndList * head;
ComplexList * next;
int Dependent() {
return dependent;
}
private:
void addChildren( EntList * );
bool hitMultNodes( EntNode * );
int abstract; ///< is our supertype abstract?
int dependent; ///< is our supertype also a subtype of other supertype(s)?
bool multSupers; ///< am I a combo-CList created to test a subtype which has >1 supertypes?
};
/// The collection of all the ComplexLists defined by the current schema.
class SC_CORE_EXPORT ComplexCollect {
public:
ComplexCollect( ComplexList * c = NULL ) : clists( c ) {
count = ( c ? 1 : 0 );
}
~ComplexCollect() {
delete clists;
}
void insert( ComplexList * );
void remove( ComplexList * ); ///< Remove this list but don't delete its hierarchy structure, because it's used elsewhere.
ComplexList * find( char * );
bool supports( EntNode * ) const;
ComplexList * clists;
private:
int count; ///< # of clist children
};
#endif