当需要用户定义的解析器来解析输入消息时,代理将调用 input 函数。 解析器必须告诉代理它声明有多少输入位流缓冲区属于它。在固定大小头的情况下,解析器声明头的大小。如果解析器要用于处理整条消息,它声明缓冲区的剩余部分。
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); }
常规解析函数(例如,cpiParseFirstChild)是当需要创建语法元素树以对 ESQL 或 Java 表达式求值时由代理调用的那些函数。例如,filter 节点在 ESQL 表达式中使用 ESQL 字段引用。必须解析此字段引用以求值表达式。将调用您的解析器的常规解析函数(可能是重复地),直到创建了请求的元素或者解析器知道它不存在。
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; }
当需要用户定义的解析器将语法元素树序列化为一个输出位流时,代理将调用 output 函数。 例如,Compute 节点可能在您用户定义的解析器的域中创建了树。例如,当需要由 MQOutput 节点输出此树时,解析器负责将表示构建的树的数据附加到输出位流缓冲区。
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; }
通常,进入消息数据是单个消息格式的,因此一个解析器负责解析消息的全部内容。所需的解析器的类名在输入消息的 MQMD 或 MQRFH2 头中的 Format 字段中定义。
但是,消息可能由多种格式组成,例如,有的一种格式的头,它后跟另一种格式的数据。在这种情况下,第一个解析器必须标识负责链中下一种格式的解析器的类名,依此类推。在用户定义的解析器中,当它需要为包含多种消息格式的消息向下浏览解析器类的链时,代理将调用 cpiNextParserClassName 实施函数。
如果您的用户定义的解析器支持解析是多种消息格式的一部分的消息格式,用户定义的解析器必须实现 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; }