Teodor Sigaev wrote:
Sorry, it isn't mentioned on page, but this example of code working only
with before 8.1 versions. In 8.1 interface to dictionary was changed.
Try attached dict_tmpl.c
2Oleg: place file on site, pls
--
Teodor Sigaev E-mail: [EMAIL PROTECTED]
WWW: http://www.sigaev.ru/
/*
* num2english dictionary by Ben Chobot <[EMAIL PROTECTED]>, based on
* example of dictionary
* Teodor Sigaev <[EMAIL PROTECTED]>
*
*/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "postgres.h"
#include "dict.h"
#include "common.h"
#include "subinclude.h"
/* special names for values */
struct nx {
char name[20];
int value;
};
static struct nx num2english_numarr[] =
{
{ "zero", 0 },
{ "one", 1 },
{ "two", 2 },
{ "three", 3 },
{ "four", 4 },
{ "five", 5 },
{ "six", 6 },
{ "seven", 7 },
{ "eight", 8 },
{ "nine", 9 },
{ "ten", 10 },
{ "eleven", 11 },
{ "twelve", 12 },
{ "thirteen", 13 },
{ "fourteen", 14 },
{ "fifteen", 15 },
{ "sixteen", 16 },
{ "seventeen", 17 },
{ "eighteen", 18 },
{ "nineteen", 19 },
{ "twenty", 20 },
{ "thirty", 30 },
{ "forty", 40 },
{ "fifty", 50 },
{ "sixty", 60 },
{ "seventy", 70 },
{ "eighty", 80 },
{ "ninety", 90 },
{ "", 999 }
};
static char *num2english_denom[]=
{
"",
"thousand",
"million",
"billion",
"trillion",
"quadrillion",
"quintillion",
"sextillion",
"septillion",
"octillion",
"nonillion",
"decillion",
"undecillion",
"duodecillion",
"tredecillion",
"quattuordecillion",
"sexdecillion",
"septendecillion",
"octodecillion",
"novemdecillion",
"vigintillion"
};
static char *cvt2(int);
static char *cvt3(int);
static char *itowords(long long);
PG_FUNCTION_INFO_V1(dinit_num2english);
Datum dinit_num2english(PG_FUNCTION_ARGS);
Datum
dinit_num2english(PG_FUNCTION_ARGS) {
/* nothing to init */
PG_RETURN_POINTER(NULL);
}
PG_FUNCTION_INFO_V1(dlexize_num2english);
Datum dlexize_num2english(PG_FUNCTION_ARGS);
Datum
dlexize_num2english(PG_FUNCTION_ARGS) {
void* dummy = PG_GETARG_POINTER(0);
char *in = (char*)PG_GETARG_POINTER(1);
char *txt = pnstrdup(in, PG_GETARG_INT32(2));
TSLexeme *res=0;
char *phrase;
char *cursor;
char *last;
int lexes = 1;
int thisLex = 0;
if ( *txt=='\0' ) {
res = palloc0(sizeof(TSLexeme));
pfree(txt);
}
else
{
phrase = itowords(atoll(txt));
if((cursor = strchr(txt,'.')) && *(cursor+1))
{
char *phrase2;
char *ptemp = phrase;
phrase2 = itowords(atoll(cursor+1));
phrase = palloc(strlen(phrase2) + strlen(ptemp) + strlen(" . ") + 1);
sprintf(phrase,"%s . %s",ptemp,phrase2);
pfree(ptemp);
pfree(phrase2);
}
pfree(txt);
for(cursor=phrase; *cursor; cursor++) if(*cursor == ' ') lexes++;
res = palloc0(sizeof(TSLexeme)*(lexes +1));
for(last=cursor=phrase; *cursor; cursor++)
{
if(*cursor == ' ')
{
res[thisLex].lexeme = palloc((cursor-last+1));
memcpy(res[thisLex].lexeme,last,(cursor-last));
res[thisLex++].lexeme[cursor-last] = '\0';
/* done with this lex. */
if(*(cursor+1) == ' ') // if the next space is *also* whitespace....
{
/* We don't want it.
Fortunately we know we'll never get more than 2 spaces in a row. */
cursor++;
}
last=cursor+1;
}
}
/* finish up this last lex */
res[thisLex].lexeme = palloc((cursor-last+1));
memcpy(res[thisLex].lexeme,last,(cursor-last));
res[thisLex++].lexeme[cursor-last] = 0;
pfree(phrase);
res[thisLex].lexeme = NULL;
}
PG_RETURN_POINTER(res);
}
/* The code below was taken from http://h21007.www2.hp.com/dspp/tech/tech_TechDocumentDetailPage_IDX/1,1701,3556,00.html
and modified slightly to fit in the postgres stored proc framework. It appears to be without copywrite. */
/* take a two-digit number and cvt to words. */
static char *cvt2(int val)
{
int i=0;
char word[80];
char *ret = 0;
while(num2english_numarr[++i].value <= val)
/* nothing */;
strcpy(word,num2english_numarr[i-1].name);
val -= num2english_numarr[i-1].value;
if (val > 0)
{
strcat(word," ");
strcat(word,num2english_numarr[val].name);
}
ret = palloc(strlen(word)+1);
memcpy(ret,word,strlen(word)+1);
return (ret);
}
/* take a 3 digit number and cvt it to words */
static char *cvt3(int val)
{
int rem, mod;
char word[80];
char *ret = 0;
word[0] = '\0';
mod = val % 100;
rem = val / 100;
if ( rem > 0 )
{
strcat(word,num2english_numarr[rem].name);
strcat(word," hundred");
if (mod > 0)
strcat(word," ");
}
if ( mod > 0 )
{
char *sub = cvt2(mod);
strcat(word, sub);
pfree(sub);
}
ret = palloc(strlen(word)+1);
memcpy(ret,word,strlen(word)+1);
return(ret);
}
/* here's the routine that does the rest */
static char *itowords(long long val)
{
long long tri; /* last three digits */
long long place = 0; /* which power of 10 we are on */
int neg=0; /* sign holder */
char temp[255]; /* temporary string space */
char word[255];
char phrase[100];
char *ret = 0;
word[0] = '\0';
/* check for negative int */
if (val < 0 )
{
neg = 1;
val = -val;
}
if ( val == 0 )
{
ret = palloc(5);
sprintf(ret,"zero");
return(ret);
}
/* what we do now is break it up into sets of three, and add the */
/* appropriate denominations to each. */
while (val > 0 )
{
phrase[0] = '\0';
tri = val % 1000; /* last three digits */
val = val / 1000; /* base 10 shift by 3 */
if (tri > 0 )
{
char *sub = cvt3(tri);
strcat(phrase,sub);
pfree(sub);
strcat(phrase," ");
}
if ((place > 0 ) && (tri > 0))
{
strcat(phrase,num2english_denom[place]);
strcat(phrase," ");
}
place++;
/* got the phrase, now put it in the string */
strcpy(temp,word);
if ((val > 0) && (tri > 0))
{
strcpy(word," ");
strcat(word,phrase);
}
else
strcpy(word,phrase);
strcat(word,temp);
}
/* remember that minus sign ? */
if (neg)
{
strcpy(temp,word);
strcpy(word,"negative ");
strcat(word,temp);
}
/* chop off the last space */
word[strlen(word)-1] = 0;
ret = palloc(strlen(word)+1);
memcpy(ret,word,strlen(word)+1);
return(ret);
}
---------------------------(end of broadcast)---------------------------
TIP 6: explain analyze is your friend