1 #include "pgrn-global.h"
2 #include "pgrn-groonga.h"
3 #include "pgrn-string.h"
4
5 static grn_ctx *ctx = &PGrnContext;
6 static struct PGrnBuffers *buffers = &PGrnBuffers;
7
8 void
PGrnStringSubstituteIndex(const char * string,unsigned int stringSize,grn_obj * output,const char * indexName,int section)9 PGrnStringSubstituteIndex(const char *string,
10 unsigned int stringSize,
11 grn_obj *output,
12 const char *indexName,
13 int section)
14 {
15 const char variable[] = "$index";
16 const size_t variableSize = sizeof(variable) - 1;
17 const char *current = string;
18 const char *end = current + stringSize;
19
20 while (current < end)
21 {
22 int char_length = grn_charlen(ctx, current, end);
23 if (char_length == 0) {
24 return;
25 }
26 if (char_length == 1 &&
27 current[0] == '$' &&
28 (end - current) >= variableSize &&
29 memcmp(current, variable, variableSize) == 0)
30 {
31 grn_text_printf(ctx, output, "%s[%d]", indexName, section);
32 current += variableSize;
33 continue;
34 }
35
36 GRN_TEXT_PUT(ctx, output, current, char_length);
37 current += char_length;
38 }
39 }
40
41 void
PGrnStringSubstituteVariables(const char * string,unsigned int stringSize,grn_obj * output)42 PGrnStringSubstituteVariables(const char *string,
43 unsigned int stringSize,
44 grn_obj *output)
45 {
46 const char *current = string;
47 const char *end = current + stringSize;
48 enum {
49 STATE_RAW,
50 STATE_ESCAPE,
51 STATE_VARIABLE_START,
52 STATE_IN_VARIABLE_BLOCK,
53 } state = STATE_RAW;
54 const char *variableSubstitutionStart = NULL;
55 enum {
56 VARIABLE_TYPE_NONE,
57 VARIABLE_TYPE_TABLE,
58 /* TODO */
59 /* VARIABLE_TYPE_INDEX_COLUMN, */
60 } variableType = VARIABLE_TYPE_NONE;
61 const char *targetStart = NULL;
62
63 while (current < end)
64 {
65 int charLength = grn_charlen(ctx, current, end);
66 if (charLength == 0) {
67 return;
68 }
69 switch (state)
70 {
71 case STATE_RAW:
72 if (charLength == 1 && current[0] == '\\')
73 {
74 state = STATE_ESCAPE;
75 }
76 else if (charLength == 1 && current[0] == '$')
77 {
78 state = STATE_VARIABLE_START;
79 variableSubstitutionStart = current;
80 }
81 else
82 {
83 GRN_TEXT_PUT(ctx, output, current, charLength);
84 }
85 break;
86 case STATE_ESCAPE:
87 GRN_TEXT_PUT(ctx, output, current, charLength);
88 state = STATE_RAW;
89 break;
90 case STATE_VARIABLE_START:
91 if (charLength == 1 && current[0] == '{')
92 {
93 state = STATE_IN_VARIABLE_BLOCK;
94 }
95 else
96 {
97 /* Not variable substitution. */
98 GRN_TEXT_PUT(ctx,
99 output,
100 variableSubstitutionStart,
101 (current - variableSubstitutionStart) + charLength);
102 state = STATE_RAW;
103 variableSubstitutionStart = NULL;
104 variableType = VARIABLE_TYPE_NONE;
105 targetStart = NULL;
106 }
107 break;
108 case STATE_IN_VARIABLE_BLOCK:
109 if (charLength == 1 &&
110 variableType == VARIABLE_TYPE_NONE &&
111 current[0] == ':')
112 {
113 grn_raw_string rawVariable;
114 rawVariable.value = variableSubstitutionStart + strlen("${");
115 rawVariable.length = current - rawVariable.value;
116 if (GRN_RAW_STRING_EQUAL_CSTRING(rawVariable, "table"))
117 {
118 variableType = VARIABLE_TYPE_TABLE;
119 targetStart = current + charLength;
120 }
121 /*
122 else if (GRN_RAW_STRING_EQUAL_CSTRING(rawVariable, "index_column"))
123 {
124 variableType = VARIABLE_TYPE_INDEX_COLUMN;
125 targetStart = current + charLength;
126 }
127 */
128 }
129 else if (charLength == 1 && current[0] == '}')
130 {
131 switch (variableType)
132 {
133 case VARIABLE_TYPE_TABLE:
134 {
135 grn_obj *indexName = &(buffers->text);
136 char tableName[GRN_TABLE_MAX_KEY_SIZE];
137 GRN_TEXT_SET(ctx,
138 indexName,
139 targetStart,
140 current - targetStart);
141 GRN_TEXT_PUTC(ctx, indexName, '\0');
142 PGrnFormatSourcesTableName(GRN_TEXT_VALUE(indexName),
143 tableName);
144 GRN_TEXT_PUTS(ctx, output, tableName);
145 break;
146 }
147 /* TODO: */
148 /* case VARIABLE_TYPE_INDEX_COLUMN: */
149 default:
150 /* Not variable substitution. */
151 GRN_TEXT_PUT(ctx,
152 output,
153 variableSubstitutionStart,
154 (current - variableSubstitutionStart) + charLength);
155 break;
156 }
157 state = STATE_RAW;
158 variableSubstitutionStart = NULL;
159 variableType = VARIABLE_TYPE_NONE;
160 targetStart = NULL;
161 }
162 break;
163 default:
164 break;
165 }
166 current += charLength;
167 }
168 }
169