Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * test_parser.c
4 : * Simple example of a text search parser
5 : *
6 : * Copyright (c) 2007-2026, PostgreSQL Global Development Group
7 : *
8 : * IDENTIFICATION
9 : * src/test/modules/test_parser/test_parser.c
10 : *
11 : *-------------------------------------------------------------------------
12 : */
13 : #include "postgres.h"
14 :
15 : #include "fmgr.h"
16 :
17 0 : PG_MODULE_MAGIC;
18 :
19 : /*
20 : * types
21 : */
22 :
23 : /* self-defined type */
24 : typedef struct
25 : {
26 : char *buffer; /* text to parse */
27 : int len; /* length of the text in buffer */
28 : int pos; /* position of the parser */
29 : } ParserState;
30 :
31 : typedef struct
32 : {
33 : int lexid;
34 : char *alias;
35 : char *descr;
36 : } LexDescr;
37 :
38 : /*
39 : * functions
40 : */
41 0 : PG_FUNCTION_INFO_V1(testprs_start);
42 0 : PG_FUNCTION_INFO_V1(testprs_getlexeme);
43 0 : PG_FUNCTION_INFO_V1(testprs_end);
44 0 : PG_FUNCTION_INFO_V1(testprs_lextype);
45 :
46 : Datum
47 0 : testprs_start(PG_FUNCTION_ARGS)
48 : {
49 0 : ParserState *pst = palloc0_object(ParserState);
50 :
51 0 : pst->buffer = (char *) PG_GETARG_POINTER(0);
52 0 : pst->len = PG_GETARG_INT32(1);
53 0 : pst->pos = 0;
54 :
55 0 : PG_RETURN_POINTER(pst);
56 0 : }
57 :
58 : Datum
59 0 : testprs_getlexeme(PG_FUNCTION_ARGS)
60 : {
61 0 : ParserState *pst = (ParserState *) PG_GETARG_POINTER(0);
62 0 : char **t = (char **) PG_GETARG_POINTER(1);
63 0 : int *tlen = (int *) PG_GETARG_POINTER(2);
64 0 : int startpos = pst->pos;
65 0 : int type;
66 :
67 0 : *t = pst->buffer + pst->pos;
68 :
69 0 : if (pst->pos < pst->len &&
70 0 : (pst->buffer)[pst->pos] == ' ')
71 : {
72 : /* blank type */
73 0 : type = 12;
74 : /* go to the next non-space character */
75 0 : while (pst->pos < pst->len &&
76 0 : (pst->buffer)[pst->pos] == ' ')
77 0 : (pst->pos)++;
78 0 : }
79 : else
80 : {
81 : /* word type */
82 0 : type = 3;
83 : /* go to the next space character */
84 0 : while (pst->pos < pst->len &&
85 0 : (pst->buffer)[pst->pos] != ' ')
86 0 : (pst->pos)++;
87 : }
88 :
89 0 : *tlen = pst->pos - startpos;
90 :
91 : /* we are finished if (*tlen == 0) */
92 0 : if (*tlen == 0)
93 0 : type = 0;
94 :
95 0 : PG_RETURN_INT32(type);
96 0 : }
97 :
98 : Datum
99 0 : testprs_end(PG_FUNCTION_ARGS)
100 : {
101 0 : ParserState *pst = (ParserState *) PG_GETARG_POINTER(0);
102 :
103 0 : pfree(pst);
104 0 : PG_RETURN_VOID();
105 0 : }
106 :
107 : Datum
108 0 : testprs_lextype(PG_FUNCTION_ARGS)
109 : {
110 : /*
111 : * Remarks: - we have to return the blanks for headline reason - we use
112 : * the same lexids like Teodor in the default word parser; in this way we
113 : * can reuse the headline function of the default word parser.
114 : */
115 0 : LexDescr *descr = palloc_array(LexDescr, 2 + 1);
116 :
117 : /* there are only two types in this parser */
118 0 : descr[0].lexid = 3;
119 0 : descr[0].alias = pstrdup("word");
120 0 : descr[0].descr = pstrdup("Word");
121 0 : descr[1].lexid = 12;
122 0 : descr[1].alias = pstrdup("blank");
123 0 : descr[1].descr = pstrdup("Space symbols");
124 0 : descr[2].lexid = 0;
125 :
126 0 : PG_RETURN_POINTER(descr);
127 0 : }
|