C パーサーを作成してから、その機能を拡張することができます。
ユーザー定義パーサーが入力メッセージを構文解析する必要がある場合に、ブローカーは入力 関数を呼び出します。 パーサーは、所有する必要があるものとして要求する入力ビット・ストリーム・バッファーの量を、ブローカーに対して知らせなければなりません。 固定サイズ・ヘッダーの場合、パーサーはヘッダーのサイズを要求します。 パーサーがメッセージ全体を処理する場合、バッファーの残りの部分を要求します。
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;
}
ユーザー定義パーサーが構文エレメント・ツリーを出力ビット・ストリームに逐次化する必要がある場合に、ブローカーは出力 関数を呼び出します。 例えば、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;
}
通常、着信メッセージ・データは単一メッセージ形式なので、1 つのパーサーがメッセージの内容全体の構文解析を担当します。 必要なパーサーのクラス名は、入力メッセージの 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;
}