情報カタログ・マネージャー プログラミングの手引きおよび解説書

API 呼び出しによって得られた出力構造の読み取り

情報を戻す情報カタログ・マネージャー API 呼び出しは、その情報を出力構造に収めます。

出力構造を読むためには、構造の各部分が他の部分の意味を定義しているため、 その構造全体を 1 つのものとしてとらえてください。

オブジェクト・インスタンスのリストを戻す API 呼び出しの場合、 オブジェクト域には、各特性ごとに複数の値が含まれている可能性があります。 このオブジェクト域には、定義域で定義された特性をマップするための値の 集合が 2 つ以上含まれることがあります。

出力構造を読むためのポインターの使い方

出力構造内の値を読むには、API 呼び出しで戻されたポインターを使用して、 その構造を指す 2 つ以上のポインターを定義してください。

ユーザーのプログラムは、出力構造を作成する API 呼び出しを出す場合、 NULL ポインターのアドレスを含むポインターを定義して、この定義済みポインターを パラメーターとして API 呼び出しに渡す必要があります。 API 機能はこの NULL ポインターにその出力構造のアドレスを割り当てます。

ユーザーは、この構造のヘッダー域と定義域を順に処理する 2 番目のポインター と、オブジェクト域を順に処理する 3 番目のポインターも定義する必要があります。

図 27 で示す pOutStruct は、出力構造の先頭を指すポインターです。 そのあとで、ヘッダー域と定義域を順に読み取るための pReadStruct を定義し、 オブジェクト域を順に読み取る pObjArea を定義することができます。

図 27. 出力構造を順に読み取るポインターの定義


出力構造ヘッダー域の先頭を指す pOutStruct およ びオブジェクト域の先頭を指す pObjArea の図。 pReadStruct はヘッダー域の先頭を指しているため、 すぐにヘッダー域および定義域をたどることができます。

ユーザーの必要に応じて、構造の値を戻されたとおりの順で読み取ることも、 特定の値を探索することもできます。 いずれの場合にも、次のことを行う必要があります。

  1. 戻される特性の数とオブジェクトの数を計算する。
  2. 各特性のデータ・タイプとデータ長を検出する。
  3. オブジェクト域を順にたどって、値の読み取りまたは検出を行う。

DG2API.H を使用して値を読み取る

情報カタログ・マネージャーでは、出力構造を読むために必要な多くの値の長さと有効な値を定義 する DG2API.H というヘッダー・ファイルが提供されています。 これらの長さを使用して、ヘッダー域、定義域、およびオブジェクト域を順に読む ために必要な C 言語コードを作成することができます。

DG2API.H ファイルで定義されている内容の完全なリストについては、 付録 B, 情報カタログ・マネージャー API ヘッダー・ファイル − DG2APIHを参照してください。

出力構造内の特性の数を計算する

API 呼び出しのなかには不特定数の特性を戻すものがあるため、その数を 計算することが必要になります。

API 呼び出しによって戻されたポインター・アドレスを使用して、 出力構造の先頭を指すようにポインターをセットしてください。

定義域内の特性の数を計算するために、ヘッダー域の 定義の長さ域 (バイト 8-15) の数値を定義域の 個別レコードの長さ (160) で割ってください。 この計算を行うためには、定義の長さの文字列を整数値に変換する必要があります。

DG2API.H では、この計算を行いやすくするために、 変数 FLG_DEFINITION_SIZE が提供されています。

図 28. 特性の数の計算

特性の数 = 定義の長さの整数値 / FLG_DEFINITION_SIZE

戻された値の集合の数を計算する

出力構造に戻された値の集合の数を計算するためには、図 30 に示すように、図 29 に示す オブジェクト域の項目カウントを構造内の特性の数で割ってください。

図 29. ヘッダー域におけるオブジェクト域の項目カウント


オブジェクト域のカウント・バイト数を強調表示した バイト・レベルでの情報カタログ・マネージャー出力構造のヘッダー域の図。

図 30. 値の集合の数の計算

値の集合の数 = オブジェクト域の項目カウント / 特性の数

ヘッダー域のフィールドは文字形式なので、図 30 の計算で使用されるときには、数値形式に変換されなければなりません。図 30 の計算にたどりつくためには、DG2API.H で定義された構造を使用することができます。

定義域の特性のデータ・タイプと長さを読み取る

特性のデータ・タイプと長さを読み取るためには、ポインターを定義して、 定義域の正しい値を読むためのポインター算術計算を行ってください。 図 31 では最初の特性のデータ・タイプと長さの位置が強調表示されています。

図 31. 最初の特性のデータ・タイプとデータ長


データ・タイプおよびデータ長のバイト数を強調表示した バイト・レベルでの情報カタログ・マネージャー出力構造のヘッダー域および定義域の図。

定義域の最初の特性のデータ・タイプを読むには、図 32 に 示すように、最初の定義レコードのヘッダー域および特性名のフィールドの長さ を、出力構造を指すフィールドの位置に加算してください。

図 32. データ・タイプ値の位置の計算

pLocationOfDataType = pOutStruct +
                      FLG_HEADER_SIZE +
                      FLG_D_PROPNM_LEN

pOutStruct は出力構造を指すポインターを表し、FLG_HEADER_SIZE は ヘッダー域の長さを表し、FLG_D_PROPNM_LEN は特性名フィールドの長さを表します。 これで、この位置にある値を別の変数に保管できるようになります。

定義域の最初の特性のデータ長を読むには、図 33 に示す ように、計算によって得られたポインターにデータ・タイプ・フィールドの 長さを加算して、データ・タイプの位置を求めてください。

図 33. データ長値の位置の計算

pLocationOfDataLen = pLocationOfDataType +
                     FLG_D_DATATYP_LEN

pLocationOfDataType は定義レコード内のデータ・タイプ・フィールド を指すポインターであり、FLG_D_DATATYP_LEN はデータ・タイプ・フィールドの 長さです。

その他の特性のデータ・タイプと長さを読むには、さらにオフセット値を加算します。 次の特性のデータ・タイプ・フィールドを求めるには、図 34 に 示すように、現在の特性のデータ・タイプを指すポインターに、1 つのデータ・レコード 全体の長さ (160) を加えてください。

図 34. 次のデータ長値の位置の計算

pLocationOfDataType = pLocationOfDataType + FLG_DEFINITION_SIZE

FLG_DEFINITION_SIZE は 160 バイトです。

オブジェクト域から順に値を読み取る

オブジェクト域の値を読むには、ポインター算術計算によってその位置を 求める必要があります。 位置を正しく計算するためには、特性のデータ・タイプと長さが分からなければ なりません。

  1. 図 35 に示すように、そのオブジェクト域の先頭を指すように ポインターに増分を加えて、オブジェクト域の最初の値を読みます。

    図 35. オブジェクト域の先頭へのポインターの移動

    pObjArea = pOutStructure + FLG_HEADER_SIZE +
               (FLG_DEFINITION_SIZE × number_of_properties)
    

    FLG_HEADER_SIZE はヘッダー域の長さであり、FLG_DEFINITION_SIZE は定義域 内の 1 つのレコードの長さです。

  2. 定義域内でこの値が属している特性のデータ・タイプとデータ長を調べます。

    CHAR または TIMESTAMP の場合
    定義域で指定された長さ値を読みます。

    VARCHAR または LONG VARCHAR の場合
    1. 値の長さを判別するために、この値に関する最初の 8 文字を読みます。
    2. ポインターを 8 バイト移動させて、値自体を読みます。

    図 36 に示すように、現行値の実際の長さをポインターに 加算して、オブジェクト域内の次の値に移動します。

    図 36. 次の値へのポインターの移動

    pObjValue = pObjArea + 値の実際の長さ
    

    図 37 は、オブジェクト域の先頭から開始して、VARCHAR 値の 長さを読み、ポインターをその値自体の先頭に移動させ、その値を読み、さらに 次の値に進む方法を示しています。

    図 37. オブジェクト域の VARCHAR 値の読み取り


    オブジェクト域から順に読み取るときの図。

DG2SAMP.C により出力構造内の値を見つける例

DG2SAMP.C プログラムは、ユーザーからオブジェクト・タイプ名を入手してか ら FLGListObjTypes 呼び出しを出して、情報カタログ・データベースで使用可能なオブジェクト・タイプ のリストを検索します。 このプログラムは、ユーザーが指定したオブジェクト・タイプの外部名と、FLGListObjTypes が出力構造に入れて戻した名前を突き合わせます。

図 38 は、FLGListObjTypes の API 呼び出しによって作成される 出力構造の形式を示しています。

図 38. FLGListObjTypes 出力構造


Figure FLAA2084 not displayed.

ユーザーおよび出力構造からの値の獲得

図 39 は、このプログラムがユーザーによって指定された 値を読み取ってその長さを計算するようすを示しています。 この図は、プログラムが出力構造内の値を NULL 文字で終了するストリングに コピーし、オブジェクト域内の値の集合の数を計算する方法も示しています。

図 39. DG2SAMP.C: ユーザーからの値の獲得

gets(pszObjName);     (1)
ulTypeLen = strlen(pszObjName);     (2)
memcpy(&pszObjEntryCount, pListStruct->pchHObjEntryCount, FLG_H_OBJAREAENT_LEN); (3)
memcpy(&pszDefLength, pListStruct->pchHDefLength, FLG_H_DEFAREA_LEN);            (4)
ulCount = (atoi(pszObjEntryCount) / (atoi(pszDefLength) / FLG_DEFINITION_SIZE)); (5)

図 39 に示したコードは、以下のステップを実行します。

(1)
ユーザーからオブジェクト・タイプ名を入力として獲得します。

(2)
オブジェクト・タイプ名の長さを判別します。

(3)
オブジェクト項目カウントを NULL 文字で終了するストリングにコピーします。

(4)
定義の長さを NULL 文字で終了するストリングにコピーします。

(5)
オブジェクト域内の値の集合の数を計算します。

オブジェクト域の先頭へのポインターの割り当て

図 40 に示すコードは、オブジェクト域の先頭に ポインターを割り当てます。

この例では、FLGListObjTypes の出力は常に 3 つの同じ特性を持つため、プログラムは 特性の数、データ・タイプ、およびデータ長を判別する必要がありません。

図 40. DG2SAMP.C: オブジェクト域の先頭へのポインターの割り当て

ulPosition = 0;                                                 (1)
pCurrPos = ((UCHAR *)pListStruct + FLG_HEADER_SIZE + ulDefLen); (2)

図 40 に示したコードは、以下のステップを実行します。

(1)
位置カウンターを 0 にセットします。

(2)
出力構造 (pListStruct) の先を指すポインターに、ヘッダー域と 定義域の長さを加算して、オブジェクト域の先頭にポインターを位置付 けます。

オブジェクト域内での移動

図 41 に示すコードは、オブジェクト域内でポインター を移動させ、ユーザーが指定した名前に一致するオブジェクト・タイプ名の 検出を試みます。

図 41. DG2SAMP.C: オブジェクト・タイプ名とオブジェクト域内のオブジェクト・タイプ名の突き合わせ

while (fNotFound && (ulPosition < ulCount))    (1)
{
  ulPosition = (ulPosition + 1);
  memcpy(&pszObjTypeId, (void *) pCurrPos, FLG_H_OBJTYPID_LEN);      (2)
  pCurrPos = pCurrPos + FLG_H_OBJTYPID_LEN;                          (3)
  memcpy(&pszLength, (void *)pCurrPos, FLG_VARIABLE_DATA_LENGTH_LEN);(4)
  ulLength = atoi(pszLength);                                        (5)
  pCurrPos = pCurrPos + FLG_VARIABLE_DATA_LENGTH_LEN;                (6)
  strncpy (pszObjectName, (void *)pCurrPos, ulLength);               (7)
  pszObjectName[ulLength]¨ = NULLCHAR;                     (8)
  if (!(strcmp(pszObjName, pszObjectName)))   (9)
    {
      fNotFound = FALSE;
      printf ("The object type ID for %s is %s.\n\n", pszObjName, pszObjTypeId);
    }
  else
    { // Move temporary pointer to the next object
      pCurrPos = pCurrPos + ulLength + FLG_DPNAME_LEN;  (10)
    }
}

図 41 に示したコードは、以下のステップを実行します。

(1)
プログラムが一致するオブジェクト名をまだ検出していないこと、および ポインターがオブジェクト域の最後の値の集合に達していないことを確認します。

(2)
最初のオブジェクト・タイプの オブジェクト・タイプ ID を pszObjTypeId にコピーします。

(3)
次の値 (オブジェクト・タイプ名の値) にポインターを移動させます。

(4)
オブジェクト・タイプ名値の最初の 8 バイト (この VARCHAR 値の長さが 入っています) をコピーします。

(5)
この長さを整数データに変換します。

(6)
変数データ長を超えてオブジェクト・タイプ名の先頭までポインターを移動させます。

(7)
そのポインター位置のオブジェクト・タイプ名を pszObjectName に コピーします。

(8)
オブジェクト・タイプ名の終わりに NULL 文字を追加して、 この値を NULL 文字で終了するストリングにします。

(9)
pszObjectName とユーザーが指定したオブジェクト・タイプ名を 比較します。

(10)
pszObjectName の値とユーザーが指定したオブジェクト・タイプ名 が一致しない場合には、次の値の集合の先頭にカーソルを移動させます。


[ ページのトップ | 前ページ | 次ページ | 目次 | 索引 ]