Subject | Re: [firebird-support] Blob External Filter |
---|---|
Author | mangara@orbisindonesia.com |
Post date | 2003-09-17T07:48:24Z |
> Hopefully this would be useful...oops, my mistake..
sorry!
/***************************************************
upper_lower_flt.h
***************************************************/
/*
declare filter uptolow input_type -101 output_type -100
entry_point 'uptolow_filter'
module_name '/usr/lib/firebird/UDF/libuplow.so.0';
declare filter lowtoup input_type -100 output_type -101
entry_point 'lowtoup_filter'
module_name '/usr/lib/firebird/UDF/libuplow.so.0';
*/
#ifndef __UPLOW_FILTER_H__
#define __UPLOW_FILTER_H__
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <ibase.h>
#define SUCCESS 0
#define FAILURE 1
#define UPPER -101
#define LOWER -100
char* u2l(char* buffer);
char* l2u(char* buffer);
ISC_STATUS uptolow_filter(short action,ISC_BLOB_CTL control);
ISC_STATUS lowtoup_filter(short action,ISC_BLOB_CTL control);
static int caller(short action,ISC_BLOB_CTL control,
short buffer_length,char *buffer,short *return_length);
static int make_file(ISC_BLOB_CTL control);
static void set_statistics (ISC_BLOB_CTL control,char eos);
static int blob_to_file(ISC_BLOB_CTL control,char eos);
static int file_to_blob(ISC_BLOB_CTL control);
static int read_file(ISC_BLOB_CTL control,char eos);
static int write_file(ISC_BLOB_CTL control);
static int transform(ISC_BLOB_CTL control,char eos);
static int transform_file(ISC_BLOB_CTL control,char eos);
static int transform_blob(ISC_BLOB_CTL control, char eos);
#endif //__UPLOW_FILTER_H__
/***************************************************
upper_lower_flt.c
***************************************************/
#include "upper_lower_flt.h"
ISC_STATUS uptolow_filter(short action,ISC_BLOB_CTL control)
{
return lowtoup_filter(action, control);
}
ISC_STATUS lowtoup_filter(short action,ISC_BLOB_CTL control)
{
int status;
FILE* fHan2cl;
char fNam2cl[32];
char eos = '9'; //end of segment marker
switch (action)
{
case isc_blob_filter_open:
status = make_file (control);
if (!status)
status = transform_blob(control,eos);
break;
case isc_blob_filter_get_segment:
status = read_file(control,eos);
break;
case isc_blob_filter_create:
status = (make_file(control));
break;
case isc_blob_filter_put_segment:
status = write_file(control);
break;
case isc_blob_filter_close:
if (control->ctl_to_sub_type == UPPER)
status = transform_file (control,eos);
memcpy(fNam2cl,(char*)&control->ctl_data[4],strlen((char*)&control->ctl_data[4]));
if (!status && (char *)control->ctl_data[0])
status = unlink (fNam2cl);
break;
}
return status;
}
static int caller(short action,ISC_BLOB_CTL control,
short buffer_length,char *buffer,short *return_length)
{
int status;
ISC_BLOB_CTL source;
source = control->ctl_source_handle;
source->ctl_status = control->ctl_status;
source->ctl_buffer = (unsigned char*)buffer;
source->ctl_buffer_length = (unsigned short)buffer_length;
status = (*source->ctl_source)(action, source);
if (return_length)
{
*return_length = source->ctl_segment_length;
}
return status;
}
static int make_file (ISC_BLOB_CTL control)
{
FILE *temp_file;
char *temp = "/tmp/ulf__XXXXXX", *file_name, *result;
file_name = (char*)malloc (32);
strncpy (file_name, temp, strlen(temp)+1);
if (!(result = mktemp (file_name)))
return FAILURE;
if (!(temp_file = fopen (file_name, "w+b")))
return FAILURE;
memset(control->ctl_data,0,8*sizeof(long));
control->ctl_data[0] = (long) temp_file;
memcpy(&control->ctl_data[4],file_name,strlen(file_name)+1);
free(file_name);
return SUCCESS;
}
static void set_statistics (ISC_BLOB_CTL control,char eos)
{
int max_seg_length = 0;
int length = 0;
int num_segs = 0;
int cur_length = 0;
FILE *temp_file;
char c;
temp_file = (FILE *)(control->ctl_data[0]);
rewind (temp_file);
for (;;)
{
c = fgetc (temp_file);
if (feof (temp_file))
break;
if (c!=eos)
{
length++;
cur_length++;
}
if (c == eos)
{
if (cur_length > max_seg_length)
max_seg_length = cur_length;
num_segs++;
cur_length = 0;
}
}
control->ctl_max_segment = max_seg_length;
control->ctl_number_segments = num_segs;
control->ctl_total_length = length;
}
static int blob_to_file(ISC_BLOB_CTL control,char eos)
{
FILE *temp_file;
short length;
char buffer [1024],*p;
int status;
int c = (int)eos;
temp_file = (FILE *)control->ctl_data[0];
while (!(status = caller (isc_blob_filter_get_segment, control,
sizeof (buffer) - 1, buffer, &length)) || status == isc_segment)
{
for (p = buffer; p < buffer + length; p++)
fputc (*p, temp_file);
}
return SUCCESS;
}
static int file_to_blob(ISC_BLOB_CTL control)
{
FILE *temp_file;
short length;
char buffer[1024],*p,c;
int status;
char fileName[32];
memcpy(fileName,&control->ctl_data[4],strlen((char*)&control->ctl_data[4])+1);
memset (buffer, 0, 1024);
temp_file = (FILE *)control->ctl_data[0];
rewind (temp_file);
p = buffer;
for (;;)
{
c = fgetc (temp_file);
if (feof (temp_file))
break;
*p++ = c;
if (p > buffer + control->ctl_buffer_length)
{
status = caller
(isc_blob_filter_put_segment,control,strlen(buffer),buffer,&length);
p = buffer;
}
}
fclose (temp_file);
unlink (fileName);
return SUCCESS;
}
static int read_file (ISC_BLOB_CTL control,char eos)
{
unsigned char *p;
FILE *temp_file;
short length;
int c;
int status;
if (control->ctl_to_sub_type != LOWER)
{
return isc_uns_ext;
}
p = control->ctl_buffer;
length = control->ctl_buffer_length;
temp_file = (FILE *)control->ctl_data [0];
for (;;)
{
c = fgetc (temp_file);
if (feof (temp_file))
{
break;
}
*p++ = c;
if ((c == (int)eos) || p >= control->ctl_buffer + length)
{
control->ctl_segment_length = p - control->ctl_buffer;
status = (c == (int)eos) ? SUCCESS: isc_segment;
return status;
}
}
return isc_segstr_eof;
}
static int write_file(ISC_BLOB_CTL control)
{
unsigned char *p;
FILE *temp_file;
short length;
unsigned char tmp;
if (control->ctl_to_sub_type != UPPER)
return isc_uns_ext;
p = control->ctl_buffer;
length = control->ctl_buffer_length;
temp_file = (FILE *)control->ctl_data[0];
while (p < control->ctl_buffer + length)
{
tmp = *p++;
fputc (tmp, temp_file);
}
return SUCCESS;
}
static int transform(ISC_BLOB_CTL control,char eos)
{
FILE *in_file, *out_file;
char *buffer, *p, *in_file_name;
int c;
int pp;
int status;
set_statistics (control,eos);
in_file = (FILE *)control->ctl_data[0];
in_file_name = (char*) malloc(32*sizeof(char));
memcpy(in_file_name,&control->ctl_data[4],strlen((char*)&control->ctl_data[4])+1);
rewind (in_file);
if (make_file (control))
return FAILURE;
out_file = (FILE *)control->ctl_data[0];
buffer = (char*)malloc (control->ctl_total_length + 1);
memset(buffer, 0, control->ctl_total_length + 1);
c = fgetc (in_file);
p = buffer;
while (!feof (in_file))
{
*p++ = (char)c;
if(p>=buffer + control->ctl_total_length)
break;
c = fgetc (in_file);
}
fclose(in_file);
unlink(in_file_name);
free (in_file_name);
switch(control->ctl_from_sub_type)
{
case UPPER:
if(control->ctl_to_sub_type != LOWER)
{
status = isc_uns_ext;
return status;
}
buffer = u2l(buffer);
break;
case LOWER:
if(control->ctl_to_sub_type != UPPER)
{
status = isc_uns_ext;
return status;
}
buffer = l2u(buffer);
break;
default:
status = isc_uns_ext;
return status;
}
p = buffer;
while (p < buffer + control->ctl_total_length)
{
pp = (int)*p++;
fputc (pp, out_file);
}
fputc (eos, out_file);
rewind (out_file);
free (buffer);
return SUCCESS;
}
static int transform_file (ISC_BLOB_CTL control,char eos)
{
if (control->ctl_to_sub_type != UPPER)
return isc_uns_ext;
transform(control,eos);
file_to_blob (control);
return SUCCESS;
}
static int transform_blob(ISC_BLOB_CTL control, char eos)
{
int status = blob_to_file (control,eos);
return transform(control,eos);
}
char* u2l(char* buffer)
{
int len = strlen(buffer);
char *tmp = (char*)malloc(len+1);
int a;
for(a=0; a<len; a++)
tmp[a] = (char)tolower((int)buffer[a]);
memcpy(buffer,tmp,len+1);
free(tmp);
return buffer;
}
char* l2u(char* buffer)
{
int len = strlen(buffer);
char *tmp = (char*)malloc(len+1);
int a;
for(a=0; a<len; a++)
tmp[a] = (char)toupper((int)buffer[a]);
memcpy(buffer,tmp,len+1);
free(tmp);
return buffer;
}