aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/preproc/c_keywords.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/preproc/c_keywords.c')
-rw-r--r--src/interfaces/ecpg/preproc/c_keywords.c51
1 files changed, 24 insertions, 27 deletions
diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c
index 38ddf6f1359..80aa7d5339c 100644
--- a/src/interfaces/ecpg/preproc/c_keywords.c
+++ b/src/interfaces/ecpg/preproc/c_keywords.c
@@ -9,8 +9,6 @@
*/
#include "postgres_fe.h"
-#include <ctype.h>
-
#include "preproc_extern.h"
#include "preproc.h"
@@ -32,39 +30,38 @@ static const uint16 ScanCKeywordTokens[] = {
*
* Returns the token value of the keyword, or -1 if no match.
*
- * Do a binary search using plain strcmp() comparison. This is much like
+ * Do a hash search using plain strcmp() comparison. This is much like
* ScanKeywordLookup(), except we want case-sensitive matching.
*/
int
-ScanCKeywordLookup(const char *text)
+ScanCKeywordLookup(const char *str)
{
- const char *kw_string;
- const uint16 *kw_offsets;
- const uint16 *low;
- const uint16 *high;
+ size_t len;
+ int h;
+ const char *kw;
+
+ /*
+ * Reject immediately if too long to be any keyword. This saves useless
+ * hashing work on long strings.
+ */
+ len = strlen(str);
+ if (len > ScanCKeywords.max_kw_len)
+ return -1;
- if (strlen(text) > ScanCKeywords.max_kw_len)
- return -1; /* too long to be any keyword */
+ /*
+ * Compute the hash function. Since it's a perfect hash, we need only
+ * match to the specific keyword it identifies.
+ */
+ h = ScanCKeywords_hash_func(str, len);
- kw_string = ScanCKeywords.kw_string;
- kw_offsets = ScanCKeywords.kw_offsets;
- low = kw_offsets;
- high = kw_offsets + (ScanCKeywords.num_keywords - 1);
+ /* An out-of-range result implies no match */
+ if (h < 0 || h >= ScanCKeywords.num_keywords)
+ return -1;
- while (low <= high)
- {
- const uint16 *middle;
- int difference;
+ kw = GetScanKeyword(h, &ScanCKeywords);
- middle = low + (high - low) / 2;
- difference = strcmp(kw_string + *middle, text);
- if (difference == 0)
- return ScanCKeywordTokens[middle - kw_offsets];
- else if (difference < 0)
- low = middle + 1;
- else
- high = middle - 1;
- }
+ if (strcmp(kw, str) == 0)
+ return ScanCKeywordTokens[h];
return -1;
}