#ifndef STATE_MACHINE_H
#define STATE_MACHINE_H

#ifdef __cplusplus
extern "C" {
#endif

/* States */

#define ERROR_STATE 0
#define START_STATE 1

/* Events */

  typedef enum {
    ERROR_EVENT,
    PARSE_RESUME_EVENT,
    START_ELEMENT_EVENT,
    END_ELEMENT_EVENT,
    CHARACTER_DATA_EVENT,
    COMMENT_EVENT,
    PI_EVENT,
    START_NS_SCOPE_EVENT,
    END_NS_SCOPE_EVENT,
    XPTR_MATCH_EVENT,
    XPTR_CLOSE_EVENT,
    NUM_EVENTS,
  } EventId;

  struct StateTableStruct;
  typedef struct StateTableStruct StateTable;

  typedef int StateId;

  typedef void (*StateTransitionHandler)(StateTable *table, void *params);
  typedef void (*StateHandlerFree)(void *params);

  StateTable *StateTable_New(void *userData);
  void StateTable_Del(StateTable *table);

  /* Returns the last value set by XML_SetUserData or NULL. */
#define StateTable_GetUserData(table) (*(void **)(table))

  int StateTable_AddStateWithHandlerParams(StateTable *table, StateId state,
                                           StateTransitionHandler handler,
                                           void *params, 
                                           StateHandlerFree destruct);

#define StateTable_AddState(table, id) \
StateTable_AddStateWithHandlerParams((table), (id), NULL, NULL, NULL)

#define StateTable_AddStateWithHandler(table, id, handler) \
StateTable_AddStateWithHandlerParams((table), (id), (handler), NULL, NULL)

  int StateTable_AddTransition(StateTable *table, StateId from, EventId event,
                               StateId next);

  /* Returns the new state id */
  StateId StateTable_Transit(StateTable *table, EventId event);

  StateId StateTable_GetState(StateTable *table);

  int StateTable_SetState(StateTable *table, StateId state);

  void _StateTable_SignalError(StateTable *table, char *filename, int lineno);

#define StateTable_SignalError(table) \
_StateTable_SignalError((table), __FILE__, __LINE__)

#ifdef __cplusplus
}
#endif

#endif /* STATE_MACHINE_H */
