Palm Programmer's Laboratory
Palm OS Programmer's Companion Volume II/3-3
3-3 PDI ライブラリの使用
このセクションでは、PDI 文脈を読み書きするためにどのように PDI ライブラリ関数を使用するか、について説明します。図3.1は、vObject の読み書きを行う際に典型的な一連のコールを示しています。
vObjectを読み取るためには、以下のことが必要です。
- PDI ライブラリへのアクセス
- PDI リーダの生成
- 入力ストリーム内の各プロパティの読み取り
- プロパティ名の読み取り
- プロパティの各パラメータの読み取り
- プロパティ値の読み取り
- PDI リーダの削除
- PDI ライブラリのアンロード
vObject に書き込むためには、以下のことが必要です。
- PDI ライブラリへのアクセス
- PDI ライタの生成
- 入力ストリーム内の各プロパティに書き込み
- プロパティ名の書き込み
- プロパティの各パラメータの書き込み
- プロパティ値の書き込み
- PDI ライタの削除
- PDI ライブラリのアンロード
このセクションのリマインダは以下の操作を説明します。
- PDI ライブラリへのアクセス?
- PDI ライブラリのアンロード?
- PDI リーダの生成?
- プロパティの読み取り?
- PDI ライタの生成?
- プロパティ値の書き込み?
- PDI バージョンの指定?
- 異なるメディアへの UDA の使用
「PDI リーダの利用例」セクションでは、PDI リーダの生成及び vCard データのデータベースへのインポートについて、詳細な例を提供します。
「PDI ライタの利用例」セクションでは、PDI ライタの生成及びデータベースから vCal フォーマットのエクスポートについて、詳細な例を提供します。
図3.1 PDI ライブラリの利用
PDI ライブラリのアクセス
PDI ライブラリを使用する前に、ライブラリをロードしてその参照値を得る必要があります。ライブラリ内の各関数はこの参照値変数を必要とします。これはシステムコードが共有ライブラリにアクセスするのに使用します。
Listing 3.2 に書かれているサンプル関数 LoadPdiLibrary は、PDI ライブラリがロードされていることを確実にし、その参照値を返します。
Listing 3.2 PDI ライブラリのロード
Static Err LoadPdiLibrary(UInt16 *libRefNum) { Err error error = SysLibFind(kPdiLibName, librefNum); if (error != 0) { error = SysLibLoad(sysResTLibrary, sysFileCPdiLib, libRefNum); } if (error) { ErrNonFatalDisplay(kPdiLibName "not found") return error; } error = PdiLibOpen(*libRefNum); return error; }
LoadPdiLibrary 関数は、既にライブラリをロードしている他のアプリケーションがあなたのコードをコールしている場合に備えて、ライブラリが既にロードされているかどうかを決めるために最初に SysLibFind 関数をコールします。SysLibFind のコールはkPdiLibName 定数( PdiLib.h ファイルで以下のように定義されています)を使用することに注意して下さい。
#define kPdiLibName "Pdi.lib"
もしライブラリがまだロードされていないなら、ライブラリをロードしてその参照値を得るために LoadPdiLibrary が SysLibLoad 関数をコールします。
ライブラリへの参照値の取得後に、ロード済のライブラリを開くために LoadPdiLibrary は PdiLibOpen 関数をコールします。
PDI ライブラリのアンロード
ライブラリを使い終わったら、アンロードしなければいけません。Listing 3.3 内のサンプル関数 UnloadPdiLibrary は、PDI ライブラリをアンロードしています。
- 訳註
- 原文では Lisiting 3.2 となっていました。
static void UnloadPdiLibrary(UInt16 refNum) { if (PdiLibClose(refNum) == 0) { SysLibRemove(refNum); } }
SysLibRemove 関数のコール後はライブラリ参照値が無効になることに注意して下さい。
PDI リーダの生成
PDI リーダを生成するためには、まずライブラリにアクセスし、その後以下に宣言されているように [[PdiReaderNew]] 関数をコールする必要があります。
PdiReaderType* PdiReaderNew(UInt16 libRefnum, UDAReader *input, UInt16 optionFlags)
PdiReaderNewの パラメータは以下の通りです。
- 「PDIライブラリへのアクセス」?で説明したライブラリ参照値。
- リーダが使用する UDA(Unified Data Access:統合データアクセス)入力ストリーム。UDA マネージャは、様々なソースからの入力を読み取ることを可能にします。このソースには、文字列や Exchange マネージャも含まれます。詳しくは、「異なるメディアへの UDA の使用」?を参照して下さい。
- リーダの解釈動作をコントロールするオプションフラグ。デフォルトのエンコーディングや互換性の設定を含みます。オプションフラグについては、Palm OS Programmer's API Referenceの第 88 章 個人データ交換ライブラリ? で説明しています。
一度リーダを生成したなら、それを使って入力ストリームからプロパティを解釈することができます。「PDI リーダの利用例」?セクションで、PDI リーダの生成と利用についての例を提供しています。
プロパティの読み取り
PDI リーダで PDI プロパティデータを読み取るために、データ読み取り関数をコールする必要があります。
- PdiReadProperty は、入力ストリームからプロパティと全パラメータを読み取ります。
- PdiReadPropertyNameは、入力ストリームから次のプロパティの名前だけを読み取ります。もしプロパティのパラメータ読み取りを個別に扱いたいならこの関数をコールできます。
- PdiReadParameter は、入力ストリームから単一のパラメータと値を読み取ります。
- 「プロパティ値の読み取り」?
入力データ読み取りの最も一般的な方法は以下のステップです。
- vObject の開始(Begin)プロパティを読み取るために、PdiReadProperty をコールします。例えば、もし vCard を読んでいるなら、入力ストリームからkPdiPRN_BEGIN_VCARDプロパティを読むまでPdiReadPropertyをコールすることができます。
- 一度オブジェクトの開始を見つけたなら、次のプロパティとそのパラメータを読み取るためにPdiReadPropertyを繰り返しコールします。
- 各プロパティで、プロパティのフィールドを読み取る必要があるときに PdiReadPropertyField 関数をコールします。
- vObject の終了(End)プロパティを読み取るまで、プロパティの読み取りを継続します。vCard では、PdiReadProperty が入力ストリームからkPdiPRN_END_VCARDプロパティを読み取るまで、プロパティを処理します。
プロパティ情報の検証
プロパティ読み取り関数のコール後、現在のプロパティについての情報を決定するために、PdiReaderType オブジェクトのフィールドにアクセスすることができます。現在のプロパティとは、現在解釈を行なっているもしくは丁度解釈を終えたプロパティです。
例えば、特定のパラメータペアがプロパティ定義に存在するかどうかを決定するために、PdiParameterPairTest マクロのpropertyフィールドを検証することができます。
プロパティ値の読み取り
単純な値を持つプロパティもあれば、構造化された値を持つプロパティもあります。構造化されたプロパティ値は、カンマやセミコロンで区切られている複数のフィールドを持っています。
例えば、以下の電話プロパティ定義は単純な値を持っています。
TEL;CELL:+1 (408) 555-4321
電話プロパティはCELLパラメータをプロパティ名と区切るためにセミコロンを含むことに注意して下さい。各プロパティの値は定義内のコロンに続きます。
以下の名前プロパティ定義は、セミコロンで区切られた4つのフィールドを含む構造化された値を持っています。
N:Smith; John;M.;Mr.; Esq.
「Palm OS Programmer's API Reference」の第 88 章「個人データ交換ライブラリ」?にパラメータを渡さなければいけません。
PDI リーダにプロパティ値のフォーマットを決定させるために、kPdiDefaultFields を指定することができます。リーダはプロパティのフォーマットを決定するために、プロパティ名を辞書から探します。
- リーダが値全体を一回の操作で解釈するために、kPdiNoFields を指定します。
- リーダが値の単一のフィールドを解釈するために、kPdiCommaFields または kPdiSemicolonFields を指定します。
- リーダが値の全フィールドを単一の値に解釈するために、kPdiConvertComma または kPdiConvertSemicolon を指定します。
通常は kPdiDefaultFields を指定することで、PDI リーダが値を適切に解釈するために辞書の情報を使用できるようになります。しかし、特に入力ストリームがカスタムプロパティを含む場合は、これはあなたのニーズと常に一致するわけではありません。
表 3.1 は、入力ストリームから同じプロパティを読み取るために異なるフォーマット定数を使用した結果です。セミコロンで区切られた7つのフィールドを含む構造化された値を持つ標準の住所( ADR )プロパティを例としています。
ADRostoffice;extended;street;locale;region;postal_code;country
ADR プロパティはセミコロンで区切られた7つのフィールドで構造化された値として vCard 標準に従って定義されているので、PDI ライブラリ辞書はそのデフォルトフォーマットを kPdiSemicolon として定義していることに注意して下さい。
表 3.1 異なる値のフォーマット形式で構造化された値の解釈
値のフォーマット形式 | PdiReadPropertyField 結果の詳細 |
---|---|
kPdiNoFields | 一度のコールで値全体が文字列として返されます。 "postoffice;extended;street;locale;region;postal_code;country" |
kPdiSemicolon | 各コールはセミコロンで区切られた単一のフィールドを値から返します。 ・最初のコールは「 postoffice 」を返します。 ・二番目のコールは「 extended 」を返します。 ・三番目のコールは「 street 」を返します。 |
kPdiComma | 各コールはカンマで区切られた単一のフィールドを値から返します。例えば、入力文字列が「postoffice,extended,street,」だった場合は以下のようになります。 ・最初のコールは「 postoffice 」を返します。 ・二番目のコールは「 extended 」を返します。 ・三番目のコールは「 street 」を返します。 |
kPdiConvertSemicolon | 一度のコールで値全体を返します。入力でセミコロンがあった場所に改行文字が入ります。 "postoffice extended street locale region postal_code country" |
kPdiConvertComma | 一度のコールで値全体を返します。入力でカンマがあった場所に改行文字が入ります。 "postoffice extended street locale region postal_code country" |
kPdiDefaultFields | PDI ライブラリ辞書は ADR フィールドのプロパティ値フォーマットを kPdiSemicolon と同じものと定義しているので、kPdiSemicolon と同じです。 |
複数の値フィールドを一度に読み取る
もし構造化された値の中のフィールドを一度に読み取ろうとするなら、またフィールドの正確な数が分からないなら、ゼロでない結果を返すまで繰り返し PdiReadPropertyField をコールすることができます。
例えば、DateTransfer.cプログラム内の以下のコードセグメントは、EXDATE プロパティ値フィールドの各フィールドを解釈します。
Listing 3.4 決定されていない値フィールド数の読み取り
while (PdiReadPropertyField(pdiRefNum, reader, &tempP, kPdiResizableBuffer, kPdiSemicolonFields) == 0) { // Resize handle to hold exception err = MemHandleResize(exceptionListH, sizeof(ExceptionsListType) + sizeof(DateType) * exceptionCount); ErrFatalDisplayIf(err != 0, "Memory full"); // Lock exception handle exceptionListP = MemHandleLock(exceptionListH); // Calc exception ptr exceptionP = (DateType*)((UInt32)exceptionListP + (UInt32)sizeof(UInt16) + (UInt32)(sizeof(DateType) * exceptionCount)); // Store exception into exception handle MatchDateTimeToken(tempP, exceptionP, NULL); // Increase exception count exceptionCount++; // Unlock exceptions list handle MemHandleUnlock(exceptionListH); }
- 注
- もし構造化された値の中のフィールドを読まないままにするなら、次の PdiReadProperty コールでそのフィールドはスキップされ、次のプロパティの始まりを適切に探します。
カスタム拡張子の追加
vObject 標準は拡張可能です。つまり、vCard やその他の vObject にカスタムプロパティを追加することができます。PDI ライブラリはこれらのカスタムプロパティを扱います。しかし、各カスタムプロパティごとにエントリをライブラリ辞書に追加するか、プロパティ値を解釈するときに kPdiDefaultFields 以外の定数を指定するか、どちらかをする必要があります。
各 PDI リーダオブジェクトと各 PDI ライタオブジェクトは、それに関連付けられたカスタム辞書を持つことができます。そのカスタム辞書をビルトイン辞書の代わりに標準として置き換えることができます。
カスタム辞書をリーダやライタに関連付けるには、最初に辞書を生成し、辞書をライタオブジェクトに関連付けるための PdiDefineWriterDictionary 関数をコールします。
- 注
- 辞書ツールについて詳しくは http://www.palmos.com/dev/tech/kb を参照して下さい。
PDI ライタの生成
PDI ライタを生成するために、最初にライブラリにアクセスし、そして PdiWriterNew 関数をコールする必要があります。これは以下のように宣言します。
PdiWriterType* PdiWriterNew(UInt16 libRefnum, UDAWriter *output, UInt8 optionFlags)
PdiWriterNew のパラメータは以下の通りです。
- PDI ライブラリのアクセス?で説明した、ライブラリの参照数値。
- ライタで使用する UDA 出力ストリーム。詳しくは、異なるメディアでの UDA の使用?を参照して下さい。
- ライタが出力を生成する振る舞いをコントロールするオプションフラグ。そのデフォルトエンコーディングと互換性設定を含みます。オプションフラグは Palm OS Programmer's API Reference の第 88 章「個人データ交換ライブラリ」?で説明しています。
一度ライタを生成したら、出力ストリームのプロパティを生成するのに使用することができます。「PDI ライタの使用例」?は、PDI ライタの生成と使用の例を提供します。
プロパティの書き込み
PDI データを PDI ライタで書き込むには、データ書き込み関数をコールする必要があります。最も一般的に使用される関数は、以下の通りです。
Writing Properties
To write PDI data with a PDI writer, you need to call the data writing functions. The most commonly used functions are:
- PdiWriteBeginObject は vObject 開始タグを出力ストリームに書き込みます。
- PdiWriteEndObject は vObject 終了タグを出力ストリームに書き込みます。
- PdiWriteProperty はプロパティを出力ストリームに書き込みます。
- PdiWritePropertyValue はプロパティ値を出力ストリームに書き込みます。
出力データを書き込む最も一般的な方法は、以下のステップに従うことです。
- vObject 開始プロパティを書き込むために、PdiWriteBeginObject をコールします。例えば、もし vCard を書き込もうとしているなら、>kPdiPRN_BEGIN_VCARD プロパティを出力ストリームに書き込むために PdiWriteBeginObject をコールします。
- 書き込みたい各プロパティごとに、次のプロパティとそのパラメータを書き込むために PdiWriteProperty をコールします。そして、プロパティの値を書き込むために PdiWritePropertyValue 関数をコールします。
- vObject 終了プロパティを書き込むために、PdiWriteEndObject をコールします。例えば、もし vCard を書き込もうとしているなら、kPdiPRN_END_VCARD プロパティを出力ストリームに書き込むために PdiWriteEndObject をコールします。
プロパティ値の書き込み
多くの場合、単に PdiWritePropertyStr をコールするだけで、カンマやセミコロンで区切られた複数フィールドを書き込むことができます。
PDI バージョンの指定
PDI ライブラリオプション定数は、PDI リーダやライタの操作をコントロールします。これらのオプションは Palm OS Programmer's API Reference の第 88 章「個人データ交換ライブラリ」?で説明します。