Estendendo o Recurso de um Analisador C

Antes de começar

Certifique-se de que tenha lido e entendido o seguinte tópico:

Implementando a Funcionalidade do Analisador

Um analisador precisa implementar os seguintes tipos de funções de implementação:
  1. funções de entrada
  2. funções de análise
  3. funções de saída

Cada tipo de função é descrito a seguir.

Implementando Funções de Entrada

As funções de entrada (por exemplo, cpiParseBuffer) são chamadas pelo intermediário quando um analisador é requerido para analisar uma mensagem de entrada. O analisador deve instruir ao intermediário de quanto do buffer do fluxo de bits de entrada ele reclama para si. No caso de um cabeçalho de comprimento fixo, o analisador reclama o tamanho do cabeçalho. Caso o analisador deva manipular a mensagem inteira, ele reclamará o restante do buffer.

Exemplo:
  1. Chamar a função cpiParseBufferEncoded:
    int cpiParseBufferEncoded(
        CciParser*  parser,
      CciContext*    context,
        int            encoding,
        int         ccsid
    ){
        PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ;
        int                rc;
    
  2. Obter um ponteiro para o buffer de mensagem e definir o deslocamento utilizando a função cpiBufferPointer:
      pc->iBuffer = (void *)cpiBufferPointer(&rc, parser);
      pc->iIndex = 0;
  3. Salvar o formato do buffer:
      pc->iEncoding = encoding;
        pc->iCcsid = ccsid;
  4. Salvar o tamanho do buffer utilizando a função cpiBufferSize:
      pc->iSize = cpiBufferSize(&rc, parser);
  5. Obter o primeiro byte no fluxo utilizando a função cpiBufferByte:
      pc->iCurrentCharacter = cpiBufferByte(&rc, parser, pc->iIndex);
  6. Definir o elemento atual para o elemento raiz utilizando a função cpiRootElement:
      pc->iCurrentElement = cpiRootElement(&rc, parser);
  7. Reconfigurar o sinalizador para assegurar-se de que a análise seja redefinida corretamente:
      pc->iInTag = 0;
    
  8. Reclamar a propriedade do restante do buffer:
      return(pc->iSize);
    }

Implementando Funções de Análise

Funções gerais de análise (por exemplo, cpiParseFirstChild) são aquelas chamadas pelo intermediário quando a árvore de elementos de sintaxe precisa ser criada para avaliar uma expressão ESQL. Por exemplo, um nó de filtro utiliza uma referência de campo ESQL em uma expressão ESQL. Essa referência de campo precisa ser resolvida para avaliar a expressão. A função geral de análise do analisador é chamada, talvez repetidamente, até que o elemento pedido seja criado ou seja reconhecido pelo analisador como não existente.

Exemplo:
void cpiParseFirstChild(
    CciParser*  parser,
  CciContext*    context,
    CciElement* element
){
    PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ;
    int                rc;

  if ((!cpiElementCompleteNext(&rc, element)) &&
            (cpiElementType(&rc, element) == CCI_ELEMENT_TYPE_NAME)) {

    while ((!cpiElementCompleteNext(&rc, element))     &&
                      (!cpiFirstChild(&rc, element)) &&
                    (pc->iCurrentElement))    {
            pc->iCurrentElement = parseNextItem(parser, context, pc->iCurrentElement);
    }
  }
           return;
}

Implementando Funções de Saída

As funções de saída (por exemplo, cpiWriteBuffer) são chamadas pelo intermediário quando um analisador é requerido para serializar uma árvore de elementos de sintaxe para um fluxo de bits de saída. Por exemplo, um nó Compute pode ter criado uma árvore no domínio do analisador definido pelo usuário. Quando essa árvore precisar ser enviada para a saída, por exemplo, um nó MQOutput, o analisador é responsável por anexar o buffer do fluxo de bits de saída com dados que representam a árvore que foi construída.

Exemplo:
int cpiWriteBufferEncoded(
    CciParser*  parser,
  CciContext*    context,
    int            encoding,
    int         ccsid
){
    PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ;
    int                initialSize = 0;
    int                rc = 0;
    const void* a;
    CciByte b;

    initialSize = cpiBufferSize(&rc, parser);
    a = cpiBufferPointer(&rc, parser);
    b = cpiBufferByte(&rc, parser, 0);

    cpiAppendToBuffer(&rc, parser, (char *)"Some test data", 14);

    return cpiBufferSize(0, parser) - initialSize;
}

Mensagens com Vários Formatos de Mensagem

Normalmente, os dados da mensagem de entrada são de um único formato da mensagem, e portanto um analisador é responsável por analisar todo o conteúdo da mensagem. O nome da classe do analisador que é necessário é definido no campo Format no cabeçalho MQMD ou MQRFH2 da mensagem de entrada.

Entretanto, a mensagem pode consistir em vários formatos, por exemplo, onde exista um cabeçalho em um formato seguido por dados em outro formato. Nesse caso, o primeiro analisador tem que identificar o nome da classe do analisador que é responsável pelo próximo formato na cadeia, e assim por diante. Em um analisador definido pelo usuário, a função de implementação cpiNextParserClassName é chamada pelo intermediário quando ele precisa navegar por uma cadeia de classes de analisador para uma mensagem composta de vários formatos da mensagem.

Se o analisador definido pelo usuário suportar a análise de um formato de mensagem que faz parte de um formato de várias mensagens, o analisador definido pelo usuário deve implementar a função cpiNextParserClassName.

Exemplo:
  1. Chamar a função cpiNextParserClassName:
    void cpiNextParserClassName(
        CciParser*  parser,
      CciContext*    context,
        CciChar*    buffer,
        int         size
    ){
        PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ;
        int                rc = 0;
    
  2. Copiar o nome da próxima classe de analisador para o intermediário:
      CciCharNCpy(buffer, pc->iNextParserClassName, size);
    
               return;
    }
Referências relacionadas
API de Nó C Definido pelo Usuário
Avisos | Marcas Registradas | Downloads | Biblioteca | Suporte | Feedback
Direitos Autorais IBM Corporation 1999, 2005 Última Atualização: 04/11/2005
as24980_