Antes de começar
Uma biblioteca de implementação carregável, ou uma LIL, é o módulo de implementação para um analisador (ou nó) em C.Uma LIL é um objeto compartilhado do UNIX ou uma DLL (Dynamic Link Library) do Windows que não tem a extensão de arquivo .dll, mas .lil.
As funções de implementação que precisam ser escritas pelo desenvolvedor estão relacionadas em Funções de Implementação de Analisador.As funções utilitárias fornecidas pelo para auxiliar esse processo estão relacionadas em Funções Utilitárias de Analisador.
O fornece a origem para um analisador de amostra definido pelo usuário chamado BipSampPluginParser.c. Esse é um analisador pseudo XML simples que pode ser utilizado em seu estado atual ou pode ser modificado.
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.
int cpiParseBufferEncoded( CciParser* parser, CciContext* context, int encoding, int ccsid ){ PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ; int rc;
pc->iBuffer = (void *)cpiBufferPointer(&rc, parser); pc->iIndex = 0;
pc->iEncoding = encoding; pc->iCcsid = ccsid;
pc->iSize = cpiBufferSize(&rc, parser);
pc->iCurrentCharacter = cpiBufferByte(&rc, parser, pc->iIndex);
pc->iCurrentElement = cpiRootElement(&rc, parser);
pc->iInTag = 0;
return(pc->iSize); }
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.
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; }
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.
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; }
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.
void cpiNextParserClassName( CciParser* parser, CciContext* context, CciChar* buffer, int size ){ PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ; int rc = 0;
CciCharNCpy(buffer, pc->iNextParserClassName, size); return; }
Cada LIL que implementa um analisador definido pelo usuário deve exportar uma função chamada bipGetParserFactory como sua função de inicialização. A função de inicialização define o nome da fábrica que o analisador definido pelo usuário suporta e as classes de objetos ou o objeto compartilhado suportado pela fábrica.
A função de inicialização precisa também criar o objeto de fábrica e definir os nomes de todos os analisadores suportados pela LIL. Uma fábrica pode suportar qualquer número de classes de objetos (analisadores). Quando um analisador é definido, uma lista de ponteiros para as funções de implementação para esse analisador é transmitida ao intermediário. Se já existir um analisador com o mesmo nome, o pedido será rejeitado.
void LilFactoryExportPrefix * LilFactoryExportSuffix bipGetParserFactory() {
CciFactory* factoryObject; int rc; static CPI_VFT vftable = {CPI_VFT_DEFAULT};
initParserConstants();
vftable.iFpCreateContext = cpiCreateContext; vftable.iFpParseBufferEncoded = cpiParseBufferEncoded; vftable.iFpParseFirstChild = cpiParseFirstChild; vftable.iFpParseLastChild = cpiParseLastChild; vftable.iFpParsePreviousSibling = cpiParsePreviousSibling; vftable.iFpParseNextSibling = cpiParseNextSibling; vftable.iFpWriteBufferEncoded = cpiWriteBufferEncoded; vftable.iFpDeleteContext = cpiDeleteContext; vftable.iFpSetElementValue = cpiSetElementValue; vftable.iFpElementValue = cpiElementValue; vftable.iFpNextParserClassName = cpiNextParserClassName; vftable.iFpSetNextParserClassName = cpiSetNextParserClassName; vftable.iFpNextParserEncoding = cpiNextParserEncoding; vftable.iFpNextParserCodedCharSetId = cpiNextParserCodedCharSetId;
A função de inicialização deve então criar uma fábrica de analisador chamando cpiCreateParserFactory. As classes de analisador suportadas pela fábrica são definidas chamando cpiDefineParserClass. O endereço do objeto fábrica (retornado por cpiCreateParserFactory) deve ser retornado ao intermediário como o valor de retorno da função de inicialização.
factoryObject = cpiCreateParserFactory(&rc, constParserFactory);
if (factoryObject) { cpiDefineParserClass(&rc, factoryObject, constPXML, &vftable); } else { /* Erro: Incapaz de criar a fábrica de analisador */ }
return(factoryObject); }
Sempre que uma instância de um objeto do analisador definido pelo usuário é criada, a função de implementação de criação de contexto cpiCreateContext é chamada pelo intermediário de mensagens. Isso permite ao analisador definido pelo usuário alocar dados da instância associados ao analisador.
CciContext* cpiCreateContext( CciParser* parser ){ PARSER_CONTEXT_ST *p;
p = (PARSER_CONTEXT_ST *)malloc(sizeof(PARSER_CONTEXT_ST));
if (p) { memset(p, 0, sizeof(PARSER_CONTEXT_ST)); } else { /* Erro: Incapaz de alocar memória */ }
return((CciContext*)p); }
Cada tipo de função é descrito a seguir.
void cpiDeleteContext( CciParser* parser, CciContext* context ){ PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ; int rc = 0; return; }
Conceitos relacionados
Planejando Extensões Definidas pelo Usuário
Extensões Definidas pelo Usuário no Ambiente de Tempo de Execução
Projetando Extensões Definidas pelo Usuário
Analisadores Definidos pelo Usuário
Tarefas relacionadas
Desenvolvendo Extensões Definidas pelo Usuário
Implementando as Amostras Fornecidas
Compilando uma Extensão Definida pelo Usuário em C
Referências relacionadas
API de Nó C Definido pelo Usuário
Avisos |
Marcas |
Downloads |
Biblioteca |
Suporte |
Feedback
![]() ![]() |
as10010_ |