チュートリアル
はじめに
umsCodeGenerator を用いたプログラム作成の流れを説明するために、ここでは簡単なサンプルを示します。 このサンプルでは、 CSV データについて以下のステップで処理を行います。
- 読み込み: 外部からデータを読み込み、umsCodeGenerator で生成されたデコード関数へデータを渡します。
- デコード: デコード関数が mapping definition に従い、データをプログラム変数へ格納します。
- エンコード: エンコード関数が mapping definition に従い、プログラム変数をデータへ格納します。
- 書き込み: umsCodeGenerator で生成されたエンコード関数からデータを受け取り、外部へデータを書き出します。
2番目と3番目のステップが umsCodeGenerator によって生成されたソースコードが処理する部分です。 その他の部分は普通にプログラムを作成します。
チュートリアルを開始するまでに、umsCodeGenerator のインストールを完了しておいてください。
なお、以降で作成するサンプルは umsCodeGenerator/yyyymmddvv/sample/tutorial に含まれています。 このディレクトリには、Java 版の XML syntax、Language syntax、C 版の XML syntax、Language syntax のサンプルが含まれています。
1. 入力データの作成
入力データと出力データの書式はどちらも同じで、"," を区切り文字とした CSV 形式とします。 以下のデータを "sample.csv" という名前でファイルに保存してください。
A,100,1.1
B,200,2.2
C,300,3.3
今回、 mappingSchema で 定義するデータの単位は、各行単位にします(ファイル全体を定義することもできます)。 行の切り出しは外付けで処理し(ステップ 1、4)、 各行の処理を mappingSchema で定義する(ステップ 2、3)ことにします。
2. mapping definition の作成
任意のエディタで mapping definition を作成します。 mapping definition は、XML syntax、Language syntax、C 版、Java 版ともに以下の記述が必要になります。 2.1 以降では、この記述に追記していく形で、Java 版の XML syntax の mapping definition を作成していきます。
<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://ums.isas.jaxa.jp/0.4/dat" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
:
</start>
</grammar>
2.1 クラス名を決める
デコード・エンコード関数を持つクラス名を決めます。今回は、"Sample" というクラス名を用います。 (この定義は、C 言語版では不要です。) ソースコードでは以下のように表せます。
class Sample {
:
}
これを、 mapping definition の XML 形式に書き直すと以下になります。
<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://ums.isas.jaxa.jp/0.4/dat" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<java:class name="Sample" xmlns:java="http://ums.isas.jaxa.jp/0.4/java">
:
</java:class>
</start>
</grammar>
2.2 エンコード関数、デコード関数の名前を決める
デコード処理、エンコード処理を行う関数の名前を決めます。 今回は、デコード処理を行う関数を"decode"、エンコード処理を行う関数を"encode"という名前にします。
次に、エンコード関数、デコード関数のインターフェースを決めます。 これらの関数のインターフェース(引数の型、引数の名前)は、umsCodeGenerator で以下のように固定です ( mappingSchema の決まりではありません)。
| 言語 | 関数種別 | インターフェース |
|---|---|---|
| C言語 | デコード関数 |
/** * デコード処理を行う。 * * @param ums__buffer 入力データ格納バッファ * @param ums__bitlen 入力データ長(bit) * ※入力データそのもののデータであり、入力格納バッファのサイズではない。 * @param ums__ex 例外情報 * @return デコードデータサイズ(bit) */ ums__bitlen_t decode( ums__bitdata_t *ums__buffer, ums__bitlen_t ums__bitlen, ums__exception_t *ums__ex ) |
| エンコード関数 |
/** * エンコード処理を行う。 * * @param ums__buffer 出力データ格納バッファ * @param ums__bitlen 出力データ格納バッファの長さ(bit) * @param ums__ex 例外情報 * @return エンコードデータサイズ(bit) */ ums__bitlen_t encode( ums__bitdata_t *ums__buffer, ums__bitlen_t ums__bitlen, ums__exception_t *ums__ex ) |
|
| Java | デコード関数 |
/** * デコード処理を行う。 * * @param ums__buffer 入力データ格納バッファ * @param ums__bitlen 入力データ長(bit) * ※入力データそのもののデータであり、入力格納バッファのサイズではない。 * @return デコードデータサイズ(bit) * @exception UMSException デコード処理エラー */ int decode( byte[] ums__buffer, int ums__bitlen ) throws UMSException |
| エンコード関数 |
/** * エンコード処理を行う。 * * @param ums__buffer 出力データ格納バッファ * @param ums__bitlen 出力データ格納バッファの長さ(bit) * @return エンコードデータサイズ(bit) * @exception UMSException エンコード処理エラー */ int encode( byte[] ums__buffer, int ums__bitlen ) throws UMSException |
ソースコードでは以下のように表すことができます。
class Sample {
:
int decode( byte[] ums__buffer, int ums__bitlen ) throws UMSException {
:
}
int encode( byte[] ums__buffer, int ums__bitlen ) throws UMSException {
:
}
}
これを、 mapping definition の XML 形式に書き直すと以下になります。
<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://ums.isas.jaxa.jp/0.4" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<java:class name="Sample" xmlns:java="http://ums.isas.jaxa.jp/0.4/java">
:
<defineFunctions>
<java:function name="decode">
<java:arg type="byte[]" name="ums__buffer" direction="in"/>
<java:arg type="int" name="ums__bitlen" direction="in"/>
<java:return type="int"/>
<java:exception type="UMSException"/>
:
</java:function>
<java:function name="encode">
<java:arg type="byte[]" name="ums__buffer" direction="out"/>
<java:arg type="int" name="ums__bitlen" direction="in"/>
<java:return type="int"/>
<java:exception type="UMSException"/>
:
</java:function>
</defineFunctions>
</java:class>
</start>
</grammar>
2.3 データ構造の定義
以下のデータについて、データ構造を mappingSchema の文法に沿った XML 形式で定義します。
A,100,1.1
以下の定義は、セパレータ "," で区切られたリスト形式で、 順に"トークン型"、"整数型"、"浮動小数点型"のデータ構造であることを示しています。
<byte>
<list separator=",">
<data type="token"/>
<data type="int"/>
<data type="double"/>
</list>
</byte>
2.4 プログラミング言語の処理の定義
次に、プログラミング言語の処理を決めます。 ここでは、処理対象のデータ全てを変数に保持する処理を採用します。 そこで、これを保持するための変数を用意することにします。 ソースコードでは以下のように表せます。
class Sample {
String sData;
int iData;
double dData;
int decode( byte[] ums__buffer, int ums__bitlen ) throws UMSException {
:
}
int encode( byte[] ums__buffer, int ums__bitlen ) throws UMSException {
:
}
}
これを、 mappingSchema の XML 形式に書き直すと以下になります。
<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://ums.isas.jaxa.jp/0.4" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<java:class name="Sample" xmlns:java="http://ums.isas.jaxa.jp/0.4/java">
<defineVariables>
<java:var class="String" name="sData"/>
<java:var type="int" name="iData"/>
<java:var type="double" name="dData"/>
</defineVariables>
<defineFunctions>
<java:function name="decode">
<java:arg type="byte[]" name="ums__buffer" direction="in"/>
<java:arg type="int" name="ums__bitlen" direction="in"/>
<java:return type="int"/>
<java:exception type="UMSException"/>
:
</java:function>
<java:function name="encode">
<java:arg type="byte[]" name="ums__buffer" direction="out"/>
<java:arg type="int" name="ums__bitlen" direction="in"/>
<java:return type="int"/>
<java:exception type="UMSException"/>
:
</java:function>
</defineFunctions>
</java:class>
</start>
</grammar>
2.5 データ構造と言語での処理の対応の定義
次に、データ構造と、プログラミング言語の処理の対応を定義します。 ここでは、データを順に変数と対応させます。 ソースコードでは以下のように表せます。
class Sample {
String sData;
int iData;
double dData;
int decode( byte[] ums__buffer, int ums__bitlen ) throws UMSException {
:
sData = ... ; // 1項目目のデコード
:
iData = ... ; // 2項目目のデコード
:
dData = ... ; // 3項目目のデコード
:
}
int encode( byte[] ums__buffer, int ums__bitlen ) throws UMSException {
:
... = sData ; // 1項目目のエンコード
:
... = iData ; // 2項目目のエンコード
:
... = dData ; // 3項目目のエンコード
:
}
}
これを、 mapping definition の XML 形式に書き直すと以下になります。
<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://ums.isas.jaxa.jp/0.4" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<java:class name="Sample" xmlns:java="http://ums.isas.jaxa.jp/0.4/java">
<defineVariables>
<java:var class="String" name="sData"/>
<java:var type="int" name="iData"/>
<java:var type="double" name="dData"/>
</defineVariables>
<defineFunctions>
<java:function name="decode">
<java:arg type="byte[]" name="ums__buffer" direction="in"/>
<java:arg type="int" name="ums__bitlen" direction="in"/>
<java:return type="int"/>
<java:exception type="UMSException"/>
<defineMapping direction="decode">
<dat:byte encode="txt" xmlns:dat="http://ums.isas.jaxa.jp/0.4/dat">
<dat:list separator=",">
<java:value-of select="sData">
<data type="token"/>
</java:value-of>
<java:value-of select="iData">
<data type="int"/>
</java:value-of>
<java:value-of select="dData">
<data type="double"/>
</java:value-of>
</dat:list>
</dat:byte>
</defineMapping>
</java:function>
<java:function name="encode">
<java:arg type="byte[]" name="ums__buffer" direction="out"/>
<java:arg type="int" name="ums__bitlen" direction="in"/>
<java:return type="int"/>
<java:exception type="UMSException"/>
<defineMapping direction="encode">
<dat:byte encode="txt" xmlns:dat="http://ums.isas.jaxa.jp/0.4/dat">
<dat:list separator=",">
<java:value-of select="sData">
<data type="token"/>
</java:value-of>
<java:value-of select="iData">
<data type="int"/>
</java:value-of>
<java:value-of select="dData">
<data type="double"/>
</java:value-of>
</dat:list>
</dat:byte>
</defineMapping>
</java:function>
</defineFunctions>
</java:class>
</start>
</grammar>
以上で mapping definition の作成は終了です。 この mapping definition を、Sample.ums という名前でファイルに保存してください。
3. その他のソースコードの作成
デコード関数、エンコード関数以外のソースコードを通常の方法で作成します。 ここでは、以下の処理を行う main メソッドを作成します。
- 入力データをファイルから読み込み、バッファに格納する。
- 入力バッファの内容を表示する。
- デコードメソッドを呼び出す。
- エンコードメソッドを呼び出す。
- 出力バッファの内容を表示する。
3.1 デコード関数・エンコード関数使用時に必要な処理
デコード関数、エンコード関数を使用するにあたって、次の処理を行う必要があります。
- ライブラリクラスの include(C 言語) / import(java)
- 初期化関数の呼び出し
- 終了関数の呼び出し
各プログラミング言語において、ライブラリ、初期化関数、終了関数は、それぞれ以下のようになります。
| 言語 | ライブラリ | 初期化関数 | 終了関数 |
|---|---|---|---|
| C言語 | ums.h | tableTools_init() | tableTools_end() |
| Java | jp.jaxa.isas.ums.runtime.* | UMSLibrary.tableTools_init() | UMSLibrary.tableTools_end() |
main 関数は以下のようになります。
import java.io.*;
import jp.jaxa.isas.ums.runtime.*;
class Main {
private static final int BUFFER_SIZE = 4096;
public static void main( String[] args ) {
String inString = null;
byte[] inBuffer = null;
int inBitlen = 0;
int decodeBitlen = 0;
byte[] outBuffer = new byte[BUFFER_SIZE];
int outBitlen = 0;
int encodeBitlen = 0;
BufferedReader br = null;
UMSLibrary.tableTools_init();
try {
Sample sample = new Sample();
br = new BufferedReader( new FileReader( args[0] ) );
while ( ( inString = br.readLine() ) != null ) {
inBitlen = inString.length() * 8;
inBuffer = inString.getBytes( "US-ASCII" );
System.out.println(
"input(" + inBitlen/8 + "*8+" + inBitlen%8 + "):<" + inString + ">" );
/* call decode method */
decodeBitlen = sample.decode( inBuffer, inBitlen );
outBitlen = BUFFER_SIZE * 8;
/* call encode method */
encodeBitlen = sample.encode( outBuffer, outBitlen );
String outString = new String( outBuffer, 0, encodeBitlen/8, "US-ASCII");
System.out.println(
"output(" + encodeBitlen/8 + "*8+" + encodeBitlen%8 + "):<" + outString.trim() + ">" );
}
} catch ( IOException ex ) {
ex.printStackTrace( System.err );
} catch ( Throwable th ) {
th.printStackTrace( System.err );
} finally {
try {
if ( br != null ) {
br.close();
}
} catch ( Exception ex ) {}
}
UMSLibrary.tableTools_end();
}
}
3.2 例外機構の使い方
エンコード関数・デコード関数は、データが定義にマッチしなかった場合などに例外を発生します。 例外機構を使用するにあたって、次の処理を行う必要があります。
- ライブラリクラスの include(C 言語) / import(java)
- 例外情報保持変数の宣言(C言語のみ)
- 例外情報初期化関数の呼び出し(C言語のみ)
- 例外情報の出力
各プログラミング言語において、ライブラリ、初期化関数、終了関数は、それぞれ以下のようになります。
| 言語 | ライブラリ | 例外情報保持変数型 | 例外情報初期化関数 | 例外情報出力関数 |
|---|---|---|---|---|
| C言語 | umsException.h | ums__exception_t | ums__exception_init | ums__exception_print |
| Java | jp.jaxa.isas.ums.runtime.UMSException | 不要 | 不要 |
main 関数は以下のようになります。
import java.io.*;
import jp.jaxa.isas.ums.runtime.*;
class Main {
private static final int BUFFER_SIZE = 4096;
public static void main( String[] args ) {
String inString = null;
byte[] inBuffer = null;
int inBitlen = 0;
int decodeBitlen = 0;
byte[] outBuffer = new byte[BUFFER_SIZE];
int outBitlen = 0;
int encodeBitlen = 0;
BufferedReader br = null;
UMSLibrary.tableTools_init();
try {
Sample sample = new Sample();
br = new BufferedReader( new FileReader( args[0] ) );
while ( ( inString = br.readLine() ) != null ) {
inBitlen = inString.length() * 8;
inBuffer = inString.getBytes( "US-ASCII" );
System.out.println(
"input(" + inBitlen/8 + "*8+" + inBitlen%8 + "):<" + inString + ">" );
/* call decode method */
decodeBitlen = sample.decode( inBuffer, inBitlen );
outBitlen = BUFFER_SIZE * 8;
/* call encode method */
encodeBitlen = sample.encode( outBuffer, outBitlen );
String outString = new String( outBuffer, 0, encodeBitlen/8, "US-ASCII");
System.out.println(
"output(" + encodeBitlen/8 + "*8+" + encodeBitlen%8 + "):<" + outString.trim() + ">" );
}
} catch ( UMSException ex ) {
ex.print( outBuffer, outBitlen );
ex.printStackTrace( System.err );
} catch ( IOException ex ) {
ex.printStackTrace( System.err );
} catch ( Throwable th ) {
th.printStackTrace( System.err );
} finally {
try {
if ( br != null ) {
br.close();
}
} catch ( Exception ex ) {}
}
UMSLibrary.tableTools_end();
}
}
上記の main メソッドを、"Main.java" という名前で保存してください。
4. umsCodeGenerator の実行
mapping definition から ソースコードを生成するため、以下のコマンドで umsCodeGenerator を実行してください。 カレントディレクトリに、"Sample.java" というファイルが生成されます。
$ txt2java -x Sample.ums
5. コンパイル・実行
これ以降は普通のプログラム開発と同じです。 これまで作成、生成したファイル(sample.csv、Main.java、Sample.java)をカレントディレクトリに格納し、 以下のコマンドを実行してください。
-
C言語
$ gcc -std=c99 -ggdb -o main -Wall -I${TABLETOOLS_HOME}/build/include -I. *.c -L${TABLETOOLS_HOME}/build/lib/ -lums -lumstt
$ ./main < sample.csv -
Java
$ javac -classpath .:$TABLETOOLS_HOME/build/classes Main.java Sample.java
$ java -cp .:$TABLETOOLS_HOME/build/classes Main sample.csv
正しく処理ができていれば、以下が表示されます。
input(9*8+0):<A,100,1.1>
output(9*8+0):<A,100,1.1>
input(9*8+0):<B,200,2.2>
output(9*8+0):<B,200,2.2>
input(9*8+0):<C,300,3.3>
output(9*8+0):<C,300,3.3>


