summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hash.c115
-rw-r--r--tests/009/json.expected96
-rw-r--r--tests/009/json.txr7
-rw-r--r--txr.114
4 files changed, 172 insertions, 60 deletions
diff --git a/hash.c b/hash.c
index 2a85d2f6..ccc10507 100644
--- a/hash.c
+++ b/hash.c
@@ -98,6 +98,107 @@ static struct hash_iter *reachable_iters;
static int hash_traversal_limit = 32;
+#if SIZEOF_PTR == 8
+
+static u64_t randbox[] = {
+ 0x41f00c9949848f1bU, 0x16f1d887e6255dbaU,
+ 0x6921f21236da5bdcU, 0x1878975147bf94e9U,
+ 0x97b6024b8cbcce22U, 0x9a803523559fc06aU,
+ 0x45d41914d268f536U, 0x40b0bc43e10af79aU,
+ 0x90e011a9c1af4d69U, 0x6ac090fe1d2917b5U,
+ 0x142a6ebeec4c304dU, 0x08fb26fc9ee5016cU,
+ 0x3f04e1d969232f74U, 0x6177e1befead7bb3U,
+ 0x778108b4e9089ab6U, 0x6a6e2ab4f012f6aeU
+};
+
+static u64_t hash_c_str(const wchar_t *str, u64_t seed, int *pcount)
+{
+ int count = *pcount << 2;
+ u64_t acc = seed;
+ u64_t ch;
+
+ while (count-- && (ch = *str++) != 0) {
+ acc ^= ch;
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ }
+
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ acc ^= randbox[acc & 0xf];
+
+ *pcount = count >> 2;
+
+ return acc;
+}
+
+static u64_t hash_buf(const mem_t *ptr, ucnum size, u64_t seed, int *pcount)
+{
+ const u64_t *buf = coerce(const u64_t *, ptr);
+ int count = *pcount << 2;
+ u64_t acc = seed;
+
+ for (; size >= sizeof *buf && count--; size -= sizeof *buf, buf++) {
+ u64_t in = *buf;
+ acc ^= in;
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ }
+
+ if (size != 0) {
+ const mem_t *tail = coerce(const mem_t *, ptr);
+ u64_t in = 0;
+
+ switch (size) {
+ case 7:
+ in |= convert(u64_t, tail[6]) << 48;
+ break;
+ /* fallthrough */
+ case 6:
+ in |= convert(u64_t, tail[5]) << 40;
+ break;
+ /* fallthrough */
+ case 5:
+ in |= convert(u64_t, tail[4]) << 32;
+ break;
+ case 4:
+ in |= convert(u64_t, tail[3]) << 24;
+ break;
+ case 3:
+ in |= convert(u64_t, tail[2]) << 16;
+ /* fallthrough */
+ case 2:
+ in |= convert(u64_t, tail[1]) << 8;
+ /* fallthrough */
+ case 1:
+ in |= convert(u64_t, tail[0]);
+ break;
+ }
+
+ acc ^= in;
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ }
+
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (64 - 1);
+ acc ^= randbox[acc & 0xf];
+
+ *pcount = count >> 2;
+
+ return acc;
+}
+
+#elif SIZEOF_PTR == 4
+
static u32_t randbox[] = {
0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,
0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,
@@ -177,6 +278,10 @@ static u32_t hash_buf(const mem_t *ptr, ucnum size, u32_t seed, int *pcount)
return acc;
}
+#else
+#error portme
+#endif
+
static ucnum hash_double(double n)
{
union hack {
@@ -1968,15 +2073,19 @@ static val set_hash_traversal_limit(val lim)
static val gen_hash_seed(void)
{
val self = lit("gen-hash-seed");
- val time = time_sec_usec();
+ val time = time_sec_nsec();
ucnum sec = convert(ucnum, c_time(car(time), self));
- ucnum usec = c_unum(cdr(time), self);
+ ucnum nsec = c_unum(cdr(time), self);
#if HAVE_UNISTD_H
ucnum pid = convert(ucnum, getpid());
#else
ucnum pid = 0;
#endif
- return unum(sec ^ (usec << 12) ^ pid);
+#if SIZEOF_PTR == 8
+ return unum((sec << 32) ^ (pid << 16) ^ nsec);
+#else
+ return unum(sec ^ (nsec << 12) ^ pid);
+#endif
}
void hash_early_init(void)
diff --git a/tests/009/json.expected b/tests/009/json.expected
index 6330a595..e9d2e644 100644
--- a/tests/009/json.expected
+++ b/tests/009/json.expected
@@ -1,54 +1,54 @@
-AST: #H(() ("web-app" #H(() ("servlet" #(#H(() ("servlet-name" "cofaxCDS") ("servlet-class" "org.cofax.cds.CDSServlet")
- ("init-param" #H(() ("dataStoreName" "cofax") ("cachePagesRefresh" 10.0) ("defaultListTemplate" "listTemplate.htm")
- ("useJSP" :false) ("cachePagesDirtyRead" 10.0) ("useDataStore" :true)
- ("cachePagesTrack" 200.0) ("dataStoreMaxConns" 100.0) ("cachePackageTagsStore" 200.0)
- ("configGlossary:poweredBy" "Cofax") ("dataStoreInitConns" 10.0)
- ("dataStorePassword" "dataStoreTestQuery") ("templateLoaderClass" "org.cofax.FilesTemplateLoader")
- ("configGlossary:poweredByIcon" "/images/cofax.gif") ("dataStoreTestQuery" "SET NOCOUNT ON;select test='test';")
- ("dataStoreConnUsageLimit" 100.0) ("dataStoreUrl" "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon")
- ("redirectionClass" "org.cofax.SqlRedirection") ("dataStoreUser" "sa")
- ("jspListTemplate" "listTemplate.jsp") ("configGlossary:adminEmail" "ksm@pobox.com")
- ("cacheTemplatesTrack" 100.0) ("defaultFileTemplate" "articleTemplate.htm")
- ("templateOverridePath" "") ("cachePagesStore" 100.0) ("templatePath" "templates")
- ("configGlossary:installationAt" "Philadelphia, PA") ("dataStoreClass" "org.cofax.SqlDataStore")
- ("cachePackageTagsTrack" 200.0) ("jspFileTemplate" "articleTemplate.jsp")
- ("dataStoreLogFile" "/usr/local/tomcat/logs/datastore.log") ("cacheTemplatesRefresh" 15.0)
- ("cacheTemplatesStore" 50.0) ("searchEngineRobotsDb" "WEB-INF/robots.db")
- ("templateProcessorClass" "org.cofax.WysiwygTemplate") ("dataStoreDriver" "com.microsoft.jdbc.sqlserver.SQLServerDriver")
- ("dataStoreLogLevel" "debug") ("cachePackageTagsRefresh" 60.0)
- ("configGlossary:staticPath" "/content/static") ("maxUrlLength" 500.0)
- ("searchEngineFileTemplate" "forSearchEngines.htm") ("searchEngineListTemplate" "forSearchEnginesList.htm"))))
- #H(() ("servlet-name" "cofaxEmail") ("servlet-class" "org.cofax.cds.EmailServlet")
- ("init-param" #H(() ("mailHost" "mail1") ("mailHostOverride" "mail2"))))
- #H(() ("servlet-name" "cofaxAdmin") ("servlet-class" "org.cofax.cds.AdminServlet"))
- #H(() ("servlet-name" "fileServlet") ("servlet-class" "org.cofax.cds.FileServlet"))
- #H(() ("servlet-name" "cofaxTools") ("servlet-class" "org.cofax.cms.CofaxToolsServlet")
- ("init-param" #H(() ("adminGroupID" 4.0) ("fileTransferFolder" "/usr/local/tomcat/webapps/content/fileTransferFolder")
- ("lookInContext" 1.0) ("dataLogMaxSize" "") ("removePageCache" "/content/admin/remove?cache=pages&id=")
- ("dataLogLocation" "/usr/local/tomcat/logs/dataLog.log") ("logMaxSize" "")
- ("betaServer" :true) ("logLocation" "/usr/local/tomcat/logs/CofaxTools.log")
- ("removeTemplateCache" "/content/admin/remove?cache=templates&id=")
- ("templatePath" "toolstemplates/") ("dataLog" 1.0) ("log" 1.0))))))
- ("taglib" #H(() ("taglib-uri" "cofax.tld") ("taglib-location" "/WEB-INF/tlds/cofax.tld")))
- ("servlet-mapping" #H(() ("cofaxAdmin" "/admin/*") ("cofaxCDS" "/") ("fileServlet" "/static/*")
- ("cofaxEmail" "/cofaxutil/aemail/*") ("cofaxTools" "/tools/*"))))))
+AST: (("web-app" (("servlet" #((("servlet-name" "cofaxCDS") ("servlet-class" "org.cofax.cds.CDSServlet")
+ ("init-param" (("configGlossary:installationAt" "Philadelphia, PA") ("configGlossary:adminEmail" "ksm@pobox.com")
+ ("configGlossary:poweredBy" "Cofax") ("configGlossary:poweredByIcon" "/images/cofax.gif")
+ ("configGlossary:staticPath" "/content/static") ("templateProcessorClass" "org.cofax.WysiwygTemplate")
+ ("templateLoaderClass" "org.cofax.FilesTemplateLoader") ("templatePath" "templates")
+ ("templateOverridePath" "") ("defaultListTemplate" "listTemplate.htm")
+ ("defaultFileTemplate" "articleTemplate.htm") ("useJSP" :false)
+ ("jspListTemplate" "listTemplate.jsp") ("jspFileTemplate" "articleTemplate.jsp")
+ ("cachePackageTagsTrack" 200.0) ("cachePackageTagsStore" 200.0)
+ ("cachePackageTagsRefresh" 60.0) ("cacheTemplatesTrack" 100.0)
+ ("cacheTemplatesStore" 50.0) ("cacheTemplatesRefresh" 15.0) ("cachePagesTrack" 200.0)
+ ("cachePagesStore" 100.0) ("cachePagesRefresh" 10.0) ("cachePagesDirtyRead" 10.0)
+ ("searchEngineListTemplate" "forSearchEnginesList.htm") ("searchEngineFileTemplate" "forSearchEngines.htm")
+ ("searchEngineRobotsDb" "WEB-INF/robots.db") ("useDataStore" :true)
+ ("dataStoreClass" "org.cofax.SqlDataStore") ("redirectionClass" "org.cofax.SqlRedirection")
+ ("dataStoreName" "cofax") ("dataStoreDriver" "com.microsoft.jdbc.sqlserver.SQLServerDriver")
+ ("dataStoreUrl" "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon")
+ ("dataStoreUser" "sa") ("dataStorePassword" "dataStoreTestQuery")
+ ("dataStoreTestQuery" "SET NOCOUNT ON;select test='test';") ("dataStoreLogFile" "/usr/local/tomcat/logs/datastore.log")
+ ("dataStoreInitConns" 10.0) ("dataStoreMaxConns" 100.0) ("dataStoreConnUsageLimit" 100.0)
+ ("dataStoreLogLevel" "debug") ("maxUrlLength" 500.0))))
+ (("servlet-name" "cofaxEmail") ("servlet-class" "org.cofax.cds.EmailServlet")
+ ("init-param" (("mailHost" "mail1") ("mailHostOverride" "mail2"))))
+ (("servlet-name" "cofaxAdmin") ("servlet-class" "org.cofax.cds.AdminServlet"))
+ (("servlet-name" "fileServlet") ("servlet-class" "org.cofax.cds.FileServlet"))
+ (("servlet-name" "cofaxTools") ("servlet-class" "org.cofax.cms.CofaxToolsServlet")
+ ("init-param" (("templatePath" "toolstemplates/") ("log" 1.0) ("logLocation" "/usr/local/tomcat/logs/CofaxTools.log")
+ ("logMaxSize" "") ("dataLog" 1.0) ("dataLogLocation" "/usr/local/tomcat/logs/dataLog.log")
+ ("dataLogMaxSize" "") ("removePageCache" "/content/admin/remove?cache=pages&id=")
+ ("removeTemplateCache" "/content/admin/remove?cache=templates&id=")
+ ("fileTransferFolder" "/usr/local/tomcat/webapps/content/fileTransferFolder")
+ ("lookInContext" 1.0) ("adminGroupID" 4.0) ("betaServer" :true))))))
+ ("servlet-mapping" (("cofaxCDS" "/") ("cofaxEmail" "/cofaxutil/aemail/*") ("cofaxAdmin" "/admin/*")
+ ("fileServlet" "/static/*") ("cofaxTools" "/tools/*")))
+ ("taglib" (("taglib-uri" "cofax.tld") ("taglib-location" "/WEB-INF/tlds/cofax.tld"))))))
Unmatched junk: ""
-AST: #("JSON Test Pattern pass1" #H(() ("object with 1 member" #("array with 1 element")))
- #H(()) #() -42.0 :true :false :null #H(() ("compact" #(1.0 2.0 3.0 4.0 5.0 6.0 7.0)) ("quotes" "&#34; \" %22 0x22 034 &#x22;")
- ("object" #H(())) ("0123456789" "digit") ("" 2.3456789012e76)
- ("ALPHA" "ABCDEFGHIJKLMNOPQRSTUVWYZ") ("digit" "0123456789")
- ("quote" "\"") (" s p a c e d " #(1.0 2.0 3.0 4.0 5.0 6.0 7.0))
- ("one" 1.0) ("alpha" "abcdefghijklmnopqrstuvwyz") ("E" 1.23456789e34)
- ("comment" "// /* <!-- --") ("special" "`1~!@#$%^&*()_+-={':[,]}|;.</>?")
- ("url" "http://www.JSON.org/") ("null" :null) ("hex" "ģ䕧覫췯ꯍ")
- ("controls" "\b\f\n\r\t") ("address" "50 St. James Street") ("# -- --> */" " ")
- ("\\/\\\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" "A key can be any string")
- ("space" " ") ("e" 1.23456789e-13) ("real" -9876.54321) ("array" #())
- ("jsontext" "{\"object with 1 member\":[\"array with 1 element\"]}")
- ("zero" 0.0) ("false" :false) ("slash" "/ & \\/") ("integer" 1234567890.0)
- ("backslash" "\\\\") ("true" :true))
+AST: #("JSON Test Pattern pass1" (("object with 1 member" #("array with 1 element")))
+ nil #() -42.0 :true :false :null (("integer" 1234567890.0) ("real" -9876.54321) ("e" 1.23456789e-13)
+ ("E" 1.23456789e34) ("" 2.3456789012e76) ("zero" 0.0) ("one" 1.0)
+ ("space" " ") ("quote" "\"") ("backslash" "\\\\") ("controls" "\b\f\n\r\t")
+ ("slash" "/ & \\/") ("alpha" "abcdefghijklmnopqrstuvwyz") ("ALPHA" "ABCDEFGHIJKLMNOPQRSTUVWYZ")
+ ("digit" "0123456789") ("0123456789" "digit") ("special" "`1~!@#$%^&*()_+-={':[,]}|;.</>?")
+ ("hex" "ģ䕧覫췯ꯍ") ("true" :true) ("false" :false) ("null" :null)
+ ("array" #()) ("object" nil) ("address" "50 St. James Street")
+ ("url" "http://www.JSON.org/") ("comment" "// /* <!-- --") ("# -- --> */" " ")
+ (" s p a c e d " #(1.0 2.0 3.0 4.0 5.0 6.0 7.0)) ("compact" #(1.0 2.0 3.0 4.0 5.0 6.0 7.0))
+ ("jsontext" "{\"object with 1 member\":[\"array with 1 element\"]}")
+ ("quotes" "&#34; \" %22 0x22 034 &#x22;") ("\\/\\\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
+ "A key can be any string"))
0.5 98.6 99.44 1066.0 10.0 1.0 0.1 1.0 2.0 2.0 "rosebud")
Unmatched junk: ""
diff --git a/tests/009/json.txr b/tests/009/json.txr
index 5c2732e8..1c705de1 100644
--- a/tests/009/json.txr
+++ b/tests/009/json.txr
@@ -57,16 +57,15 @@
@(end)
@;
@; Recognize an object: a collection of string/value pairs,
-@; turning them into an equal-based hash table
+@; turning them into a list.
@;
@(define object (v))@\
@(local p e pair)@\
- @(ws){@(ws)@(coll :gap 0 :vars (pair))@\
+ @(ws){@(ws)@(coll :gap 0 :vars (v))@\
@(string p):@(value e)@/,?/@\
- @(bind pair (p e))@\
+ @(bind v (p e))@\
@(until)}@\
@(end)}@(ws)@\
- @(bind v @(progn ^#H((:equal-based) ,*pair)))@\
@(end)
@;
@; Recognize an array.
diff --git a/txr.1 b/txr.1
index aa631433..28274987 100644
--- a/txr.1
+++ b/txr.1
@@ -53190,10 +53190,12 @@ The optional
value perturbs the hashing function used by
.code hash-equal
for strings and buffer objects. This seed value must be a nonnegative integer
-no wider than 32 bits: that is, in the range 0 to 4294967295.
-If the value isn't specified, it defaults to zero.
-Effectively, each possible value of the seed specifies a different hashing
-function. If two objects
+no wider than 64 bits: that is, in the range 0 to 18446744073709551615.
+If the value isn't specified, it defaults to zero. On systems with 32 bit
+addresses, only the low 32 bits of this value may be significant.
+
+Effectively, each possible value of the significant part of the seed specifies
+a different hashing function. If two objects
.code A
and
.code B
@@ -53625,7 +53627,9 @@ degrade.
The value of
.code *hash-seed*
-must be a nonnegative integer, no wider than 32 bits.
+must be a nonnegative integer, no wider than 64 bits.
+On systems with 32 bit addresses, only the least significant 32 bits of
+this value may be significant.
.coNP Function @ gen-hash-seed
.synb