3 * Teodor Sigaev <teodor@sigaev.ru>
15 #define SYNBUFLEN 4096
28 PG_FUNCTION_INFO_V1(syn_init);
29 Datum syn_init(PG_FUNCTION_ARGS);
31 PG_FUNCTION_INFO_V1(syn_lexize);
32 Datum syn_lexize(PG_FUNCTION_ARGS);
35 findwrd(char *in, char **end)
40 while (*in && isspace(*in))
47 while (*in && !isspace(*in))
55 compareSyn(const void *a, const void *b)
57 return strcmp(((Syn *) a)->in, ((Syn *) b)->in);
62 syn_init(PG_FUNCTION_ARGS)
75 if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL)
77 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
78 errmsg("NULL config")));
80 in = PG_GETARG_TEXT_P(0);
81 if (VARSIZE(in) - VARHDRSZ == 0)
83 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
84 errmsg("VOID config")));
86 filename = text2char(in);
87 PG_FREE_IF_COPY(in, 0);
88 if ((fin = fopen(filename, "r")) == NULL)
90 (errcode_for_file_access(),
91 errmsg("could not open file \"%s\": %m",
94 d = (DictSyn *) malloc(sizeof(DictSyn));
99 (errcode(ERRCODE_OUT_OF_MEMORY),
100 errmsg("out of memory")));
102 memset(d, 0, sizeof(DictSyn));
104 while (fgets(buf, SYNBUFLEN, fin))
106 slen = strlen(buf) - 1;
112 d->len = (d->len) ? 2 * d->len : 16;
113 d->syn = (Syn *) realloc(d->syn, sizeof(Syn) * d->len);
118 (errcode(ERRCODE_OUT_OF_MEMORY),
119 errmsg("out of memory")));
123 starti = findwrd(buf, &end);
127 if (end >= buf + slen)
130 starto = findwrd(end + 1, &end);
135 d->syn[cur].in = strdup(lowerstr(starti));
136 d->syn[cur].out = strdup(lowerstr(starto));
137 if (!(d->syn[cur].in && d->syn[cur].out))
141 (errcode(ERRCODE_OUT_OF_MEMORY),
142 errmsg("out of memory")));
152 qsort(d->syn, d->len, sizeof(Syn), compareSyn);
155 PG_RETURN_POINTER(d);
159 syn_lexize(PG_FUNCTION_ARGS)
161 DictSyn *d = (DictSyn *) PG_GETARG_POINTER(0);
162 char *in = (char *) PG_GETARG_POINTER(1);
167 if (!PG_GETARG_INT32(2))
168 PG_RETURN_POINTER(NULL);
171 key.in = lowerstr(pnstrdup(in, PG_GETARG_INT32(2)));
173 found = (Syn *) bsearch(&key, d->syn, d->len, sizeof(Syn), compareSyn);
177 PG_RETURN_POINTER(NULL);
179 res = palloc(sizeof(char *) * 2);
181 res[0] = pstrdup(found->out);
184 PG_RETURN_POINTER(res);