--- /dev/null
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * SPDX-License-Identifier: curl
+ *
+ ***************************************************************************/
+#include <stdio.h>
+#include <curl/curl.h>
+
+/*
+ * Use this tool to generate an updated table for the Curl_getn_scheme_handler
+ * function in url.c.
+ */
+
+struct detail {
+ const char *n;
+ const char *ifdef;
+};
+
+static const struct detail scheme[] = {
+ {"dict", "#ifndef CURL_DISABLE_DICT" },
+ {"file", "#ifndef CURL_DISABLE_FILE" },
+ {"ftp", "#ifndef CURL_DISABLE_FTP" },
+ {"ftps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)" },
+ {"gopher", "#ifndef CURL_DISABLE_GOPHER" },
+ {"gophers", "#if defined(USE_SSL) && !defined(CURL_DISABLE_GOPHER)" },
+ {"http", "#ifndef CURL_DISABLE_HTTP" },
+ {"https", "#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" },
+ {"imap", "#ifndef CURL_DISABLE_IMAP" },
+ {"imaps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP)" },
+ {"ldap", "#ifndef CURL_DISABLE_LDAP" },
+ {"ldaps", "#if !defined(CURL_DISABLE_LDAP) && \\\n"
+ " !defined(CURL_DISABLE_LDAPS) && \\\n"
+ " ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \\\n"
+ " (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))" },
+ {"mqtt", "#ifndef CURL_DISABLE_MQTT" },
+ {"pop3", "#ifndef CURL_DISABLE_POP3" },
+ {"pop3s", "#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3)" },
+ {"rtmp", "#ifdef USE_LIBRTMP" },
+ {"rtmpt", "#ifdef USE_LIBRTMP" },
+ {"rtmpe", "#ifdef USE_LIBRTMP" },
+ {"rtmpte", "#ifdef USE_LIBRTMP" },
+ {"rtmps", "#ifdef USE_LIBRTMP" },
+ {"rtmpts", "#ifdef USE_LIBRTMP" },
+ {"rtsp", "#ifndef CURL_DISABLE_RTSP" },
+ {"scp", "#if defined(USE_SSH) && !defined(USE_WOLFSSH)" },
+ {"sftp", "#if defined(USE_SSH)" },
+ {"smb", "#if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) && \\\n"
+ " (SIZEOF_CURL_OFF_T > 4)" },
+ {"smbs", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMB) && \\\n"
+ " defined(USE_CURL_NTLM_CORE) && (SIZEOF_CURL_OFF_T > 4)" },
+ {"smtp", "#ifndef CURL_DISABLE_SMTP" },
+ {"smtps", "#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP)" },
+ {"telnet", "#ifndef CURL_DISABLE_TELNET" },
+ {"tftp", "#ifndef CURL_DISABLE_TFTP" },
+ {"ws", "#if defined(USE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" },
+ {"wss", "#if defined(USE_WEBSOCKETS) && \\\n"
+ " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" },
+ { NULL, NULL }
+};
+
+unsigned int calc(const char *s, int add, int shift)
+{
+ const char *so = s;
+ unsigned int c = add;
+ while(*s) {
+ c <<= shift;
+ c += *s;
+ s++;
+ }
+ return c;
+}
+
+unsigned int num[100];
+unsigned int ix[100];
+
+static void showtable(int try, int init, int shift)
+{
+ int nulls = 0;
+ int i;
+ for(i = 0; scheme[i].n; ++i)
+ num[i] = calc(scheme[i].n, init, shift);
+ for(i = 0; scheme[i].n; ++i)
+ ix[i] = num[i] % try;
+ printf("/*\n"
+ " unsigned int c = %d\n"
+ " while(l) {\n"
+ " c <<= %d;\n"
+ " c += Curl_raw_tolower(*s);\n"
+ " s++;\n"
+ " l--;\n"
+ " }\n"
+ "*/\n", init, shift);
+
+ printf(" static const struct Curl_handler * const protocols[%d] = {", try);
+
+ /* generate table */
+ for(i=0; i < try; i++) {
+ int match = 0;
+ int j;
+ for(j=0; scheme[j].n; j++) {
+ if(ix[j] == i) {
+ printf("\n");
+ printf("%s\n", scheme[j].ifdef);
+ printf(" &Curl_handler_%s,\n", scheme[j].n);
+ printf("#else\n NULL,\n");
+ printf("#endif");
+ match = 1;
+ nulls = 0;
+ break;
+ }
+ }
+ if(!match) {
+ if(!nulls || (nulls>10)) {
+ printf("\n ");
+ nulls = 0;
+ }
+ printf(" NULL,", nulls);
+ nulls++;
+ }
+ }
+ printf("\n };\n");
+}
+
+int main(void)
+{
+ int i;
+ int try;
+ int besttry = 9999;
+ int bestadd = 0;
+ int bestshift = 0;
+ int add;
+ int shift;
+ for(shift = 0; shift < 8; shift++) {
+ for(add = 0; add < 999; add++) {
+ for(i = 0; scheme[i].n; ++i) {
+ unsigned int v = calc(scheme[i].n, add, shift);
+ int j;
+ int badcombo = 0;
+ for(j=0; j < i; j++) {
+
+ if(num[j] == v) {
+ /*
+ printf("NOPE: %u is a dupe (%s and %s)\n",
+ v, scheme[i], scheme[j]);
+ */
+ badcombo = 1;
+ break;
+ }
+ }
+ if(badcombo)
+ break;
+ num[i] = v;
+ }
+#if 0
+ for(i = 0; scheme[i].n; ++i) {
+ printf("%u - %s\n", num[i], scheme[i].n);
+ }
+#endif
+ /* try different remainders to find smallest possible table */
+ for(try = 28; try < 199; try++) {
+ int good = 1;
+ for(i = 0; scheme[i].n; ++i) {
+ ix[i] = num[i] % try;
+ }
+ /* check for dupes */
+ for(i = 0; scheme[i].n && good; ++i) {
+ int j;
+ for(j=0; j < i; j++) {
+ if(ix[j] == ix[i]) {
+ /* printf("NOPE, try %u causes dupes (%d and %d)\n", try, j, i); */
+ good = 0;
+ break;
+ }
+ }
+ }
+ if(good) {
+ if(try < besttry) {
+ besttry = try;
+ bestadd = add;
+ bestshift = shift;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ showtable(besttry, bestadd, bestshift);
+}