Antes de empezar
Una biblioteca de implementación cargable o LIL es el módulo de implementación para un analizador C (o un nodo). LIL es un objeto compartido de UNIX o una biblioteca de enlace dinámico (DLL) que no tiene la extensión de archivo .dll, sino .lil.
Las funciones de implementación que el desarrollador tenga que escribir aparecen listadas en la sección Funciones de implementación de analizador. Las funciones de programa de utilidad que WebSphere Business Integration Message Broker proporciona para ayudar a este proceso aparecen listadas en la sección Funciones de programa de utilidad de analizador.
WebSphere Business Integration Message Broker proporciona el origen para un analizador definido por el usuario de ejemplo que se denomina BipSampPluginParser.c. Es un analizador pseudo XML que se puede utilizar en el estado actual o se puede modificar.
Las funciones de entrada (por ejemplo, cpiParseBuffer) las invoca el intermediario cuando se solicita a un analizador que analice un mensaje de entrada. El analizador debe indicar al intermediario qué cantidad de almacenamiento intermedio de corriente de bits de entrada reclama como suyo. En el caso de una cabecera de tamaño fijo, el analizador reclama el tamaño de la cabecera. Si el analizador tiene la intención de manejar todo el mensaje, reclama el resto del almacenamiento intermedio.
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); }
Las funciones de análisis general (por ejemplo, cpiParseFirstChild) son las que invoca el intermediario cuando tiene que crearse el árbol de elementos de sintaxis para poder evaluar una expresión ESQL. Por ejemplo, un nodo de filtro utiliza una referencia de campo ESQL en una expresión ESQL. Esta referencia de campo debe resolverse para poder evaluar la expresión. Se invoca la función de análisis general del analizador, quizás de forma reiterada, hasta que se cree el elemento solicitado o bien hasta que el analizador se cerciore de que no existe.
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; }
Las funciones de salida (por ejemplo, cpiWriteBuffer) las invoca el intermediario cuando se solicita que un analizador ejecute en serie un árbol de elementos de sintaxis en una corriente de bits de salida. Por ejemplo, un nodo Compute podría haber creado un árbol en el dominio del analizador definido por el usuario. Cuando este árbol necesita generarse por ejemplo, mediante un nodo MQOutput, el analizador es responsable de añadir el almacenamiento intermedio de corriente de bits de salida con datos que representan el árbol que se ha creado.
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, los datos del mensaje entrada pertenecen a un formato de mensaje individual, con lo cual el analizador es responsable de analizar todo el contenido del mensaje. El nombre de clase del analizador que es necesario está definido en el campo Format (formato) de la cabecera MQMD o MQRFH2 del mensaje de entrada.
Sin embargo, el mensaje puede constar de múltiples formatos, por ejemplo, el caso en que hay una cabecera en un formato seguido por datos en otro formato. En este caso, el analizador tiene que identificar el nombre de clase del analizador que es responsable del siguiente formato de la cadena, y así sucesivamente. En un analizador definido por el usuario, la función de implementación cpiNextParserClassName la invoca el intermediario cuando necesita navegar hacia abajo de la cadena de clases de analizadores de un mensaje que está compuesto por formatos de mensajes múltiples.
Si el analizador definido por el usuario da soporte al análisis de un formato de mensaje que forma parte de un formato de mensajes múltiples, el analizador definido por el usuario debe implementar la función 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 un analizador definido por el usuario debe exportar una función denominada bipGetParserFactory como la función de inicialización. La función de inicialización define el nombre de la fábrica que el analizador definido por el usuario soporta y las clases de objetos o el objeto compartido, soportados por la fábrica.
La función de inicialización también debe crear el objeto de fábrica y definir los nombres de todos los analizadores soportados por LIL. Una fábrica puede dar soporte a cualquier número de clases de objetos (analizadores). Cuando se define un analizador, se transfiere una lista de punteros a las funciones de implementación de dicho analizador. Si ya existe un analizador que tenga el mismo nombre, se rechaza la petición.
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 continuación, la función de inicialización debe crear una fábrica de analizador invocando cpiCreateParserFactory. Las clases de analizadores soportados por la fábrica se definen invocando cpiDefineParserClass. La dirección del objeto de fábrica (devuelta por la función cpiCreateParserFactory) debe devolverse al intermediario como el valor de retorno de la función de inicialización.
factoryObject = cpiCreateParserFactory(&rc, constParserFactory);
if (factoryObject) { cpiDefineParserClass(&rc, factoryObject, constPXML, &vftable); } else { /* Error: No se ha podido crear fábrica de analizador */ }
return(factoryObject); }
Siempre que se crea una instancia de un objeto de analizador definido por el usuario, el intermediario de mensajes invoca la función de implementación de creación de contexto cpiCreateContext. Esto permite al analizador definido por el usuario asignar datos de instancia asociados al analizador.
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 { /* Error: No se ha podido asignar memoria */ }
return((CciContext*)p); }
Cada tipo de función se describe a continuación.
void cpiDeleteContext( CciParser* parser, CciContext* context ){ PARSER_CONTEXT_ST* pc = (PARSER_CONTEXT_ST *)context ; int rc = 0; return; }
Conceptos relacionados
Planificación de extensiones definidas por el usuario
Extensiones definidas por el usuario en el entorno de ejecución
Diseño de extensiones definidas por el usuario
Analizadores definidos por el usuario
Tareas relacionadas
Desarrollo de extensiones definidas por el usuario
Implementación de los ejemplos proporcionados
Compilación de una extensión definida por el usuario en C
Referencia relacionada
API de analizador C definida por el usuario
Avisos |
Marcas registradas |
Descargas |
Biblioteca |
Soporte |
Información de retorno (feedback)
![]() ![]() |
as10010_ |