ページの先頭行へ戻る
Interstage Data Effector V9.3.x リファレンス集
FUJITSU Software

6.5 ユーザー定義関数

Data Effectorの条件式からcall関数で呼び出す、ユーザー定義関数の作成例を示します。

ユーザー定義関数の仕様

入力文字列中の半角英字を大文字に変換します。

作成

以下に、ユーザー定義関数の作成例を示します。

#if defined( WIN32 )
#define	DEFUNC_QUALIFIER	__declspec(dllexport)
#else
#define	DEFUNC_QUALIFIER
#endif

#if defined(__cplusplus)
extern "C" DEFUNC_QUALIFIER int Defunc( int, void **, void ** );
#endif

#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>

#include "libAsis.h"

/* ユーザー定義関数の仕様
 * ・引数として、ASCII文字だけから構成される文字列を受け取る
 * ・その文字列に含まれる小文字を大文字に変換した文字列を返す
 */

/* エラーコード */
enum {
	C_UFNC_NORMAL_END				= 0,
	C_UFNC_ERR_UNKNOWN_CALLCODE,
	C_UFNC_ERR_INSUFFICIENT_MEMORY,
	C_UFNC_ERR_NULL_HANDLE,
	C_UFNC_ERR_NULL_DATA,
	C_UFNC_ERR_TOO_FEW_OR_TOO_MANY_ARGUMENTS,
	C_UFNC_ERR_INVALID_ARGUMENT,
	C_UFNC_ERR_NULL_RETURN_DATA
};

/* ハンドル */
struct userhandle_tag {
	int				sz_buffer;			/* 作業領域のサイズ */
	char			*buffer;			/* 作業領域 */
};

/* 呼び出しコード別の処理 */
/* 環境開設 */
struct userhandle_tag* defunc_open( void );

/* 環境閉鎖 */
void defunc_close(
	struct userhandle_tag*
	);

/* 変換実行 */
int	defunc_exec(
	struct userhandle_tag*,
	int,
	char **,
	char **
	);

/* 領域解放 */
void defunc_free(
	struct userhandle_tag*,
	char *
	);

/* ユーザー定義関数の実装 */
DEFUNC_QUALIFIER int Defunc(
        int    Oper,  /* 呼び出し種別 */
        void   **Handle,  /* ハンドル */
        void   **Data   /* 引数, および返却用の領域 */
   )
{
       struct userhandle_tag    *handle = NULL;
       int	   ret = C_UFNC_NORMAL_END;

	switch( Oper ) {
	case DE_USER_FUNCTION_THREAD_OPEN:
		/* 環境の開設 */
		handle = defunc_open( );
		if( handle == NULL ) {
			/* 失敗 */
			ret = C_UFNC_ERR_INSUFFICIENT_MEMORY;
		}
		else {
			/* ハンドルを返却 */
			*Handle = handle;
		}
		break;

	case DE_USER_FUNCTION_THREAD_CLOSE:
		/* 環境の閉鎖 */
		handle = (struct userhandle_tag*)*Handle;

		defunc_close( handle );
		break;

	case DE_USER_FUNCTION_EXEC:
		/* 変換の実行 */

		if( *Handle == NULL ) {
			return C_UFNC_ERR_NULL_HANDLE;
		}
		if( *Data == NULL ) {
			return C_UFNC_ERR_NULL_DATA;
		}

		handle = (struct userhandle_tag *)*Handle;

		{
			int				num_arg;		/* 引数の数 */
			int				offset;
			char			**arg_list;		/* 引数のリスト */
			char			*result;		/* 結果が格納された領域のポインタ */

			/* 引数の情報の分解 */
			memcpy(&num_arg, (char*)(Data[0]), sizeof(int));
			memcpy(&offset, (char*)(Data[0]) + sizeof(int), sizeof(int));
			arg_list = (char**)((char*)(Data[0]) + + sizeof(int)*2 + offset);

			/* 変換処理の実施 */
			ret = defunc_exec(handle, num_arg, arg_list, &result );
			if( ret != C_UFNC_NORMAL_END ) {
				return ret;
			}
			else {
				/* 変換結果の設定 */
				Data[0] = result;
			}
		}

		break;

	case DE_USER_FUNCTION_FREE:
		/* 領域の解放*/

		handle = (struct userhandle_tag *)*Handle;

		{
			char			*result;		/* 結果が格納された領域のポインタ */

			result = (char*)Data[0];

			defunc_free( handle, result );
		}

		break;

	default:
		return C_UFNC_ERR_UNKNOWN_CALLCODE;
	}

	return C_UFNC_NORMAL_END;
}

/* 環境開設処理 */
struct userhandle_tag * defunc_open(
	void
	)
{
	struct userhandle_tag	*wk_handle;

	/* ハンドルの獲得 */
	wk_handle = (struct userhandle_tag *) calloc(1, sizeof(struct userhandle_tag ));
	if( wk_handle == NULL ) {
		return NULL;
	}

	/* 作業領域の獲得 */
	wk_handle->sz_buffer = 1024;
	wk_handle->buffer = (char*)malloc( wk_handle->sz_buffer );
	if( wk_handle->buffer == NULL ) {
		free( wk_handle );
		return NULL;
	}

	/* 獲得したハンドルを返す */

	return wk_handle;
}

/* 環境閉鎖処理 */
void defunc_close(
	struct userhandle_tag			*handle
	)
{
	if( handle != NULL ) {
		if( handle->buffer != NULL ) {
			free( handle->buffer );
			handle->buffer = NULL;
		}
		free( handle );
		handle = NULL;
	}

	return ;
}

/* 変換実行 */
int defunc_exec(
	struct userhandle_tag			*handle,
	int
	num_arg,
	char							**arg_list,
	char 							**result
	)
{
	/* 入力文字列のポインタ */
	const char		*instr;
	/* 入力文字列の長さ */
	int				len_instr;

	/* 出力文字列 */
	char			*outstr;
	/* 出力文字列の長さ */
	int				len_outstr;

	int				i;

	outstr = NULL;

	if( num_arg != 1 ) {
		return C_UFNC_ERR_TOO_FEW_OR_TOO_MANY_ARGUMENTS;
	}

	/* 引数の情報 */
	instr = arg_list[0];
	len_instr = strlen( instr );

	/* ASCII文字なので変換後の長さは入力の長さと同じ */
	len_outstr = len_instr;

	/*
	 * 変換結果用のバッファの獲得
	 * ・ハンドル内の作業領域に変換結果を持つ
	 */
	if( handle->sz_buffer < len_outstr + 1 ) {
		/* サイズが足りないので拡張する */
		char			*tmp_ptr;
		int				tmp_sz;

		tmp_sz = len_outstr + 1;
		tmp_ptr = (char*)realloc( handle->buffer, tmp_sz );
		if( tmp_ptr == NULL ) {
			return C_UFNC_ERR_INSUFFICIENT_MEMORY;
		}
		handle->buffer = tmp_ptr;
		handle->sz_buffer = tmp_sz;
	}
	outstr = handle->buffer;

	/* 変換 */
	for( i=0; i<len_instr; i++ ) {
		outstr[i] = toupper( instr[i] );
	}
	outstr[i] = '\0';

	/* 返却データをセット */
	*result = outstr;

	return C_UFNC_NORMAL_END;
}

/* 領域解放 */
void defunc_free(
	struct userhandle_tag		*handle,
	char						*result
	)
{
	/* 変換結果の領域はハンドルにある作業領域なので解放しない */

	if( result != NULL ) {
		result[0] = '\0';
	}

	return;
}