summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hash.c162
-rw-r--r--hash.h2
-rw-r--r--lib.c4
-rw-r--r--lib.h6
-rw-r--r--struct.c6
-rw-r--r--tests/009/json.expected92
6 files changed, 151 insertions, 121 deletions
diff --git a/hash.c b/hash.c
index 4d8fcf04..68a7e75c 100644
--- a/hash.c
+++ b/hash.c
@@ -43,6 +43,7 @@
#include "stream.h"
#include "eval.h"
#include "cadr.h"
+#include "itypes.h"
#include "hash.h"
typedef enum hash_flags {
@@ -53,7 +54,7 @@ typedef enum hash_flags {
} hash_flags_t;
struct hash_ops {
- cnum (*hash_fun)(val, int *);
+ cnum (*hash_fun)(val, int *, ucnum);
val (*equal_fun)(val, val);
val (*assoc_fun)(val key, cnum hash, val list);
val (*acons_new_c_fun)(val key, cnum hash, loc new_p, loc list);
@@ -63,6 +64,7 @@ struct hash_ops {
{ hash, equal, assoc, acons }
struct hash {
+ ucnum seed;
hash_flags_t flags;
struct hash *next;
val table;
@@ -91,69 +93,83 @@ val weak_keys_k, weak_vals_k, equal_based_k, eql_based_k, userdata_k;
static struct hash *reachable_weak_hashes;
static struct hash_iter *reachable_iters;
-static int hash_str_limit = 128, hash_rec_limit = 32;
+static int hash_str_limit = INT_MAX, hash_rec_limit = 32;
/* C99 inline instantiations. */
#if __STDC_VERSION__ >= 199901L
loc gethash_l(val hash, val key, loc new_p);
#endif
-/*
- * This is is an adaptation of hashpjw, from Compilers: Principles, Techniques
- * and Tools, Aho, Sethi, Ulman, 1988. P. 436. The register is wider by
- * a few bits, and we bring down five overflow bits instead of four.
- * We don't reduce the final result modulo a small prime, but leave it
- * as it is; let the hashing routines do their own reduction.
- */
-static unsigned long hash_c_str(const wchar_t *str)
+static u32_t randbox[] = {
+ 0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U,
+ 0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU,
+ 0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU,
+ 0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU,
+};
+
+static u32_t hash_c_str(const wchar_t *str, u32_t seed)
{
int count = hash_str_limit;
- unsigned long h = 0;
- while (*str && count--) {
- unsigned long g;
- h = (h << 4) + *str++;
- g = h & 0x7C000000;
- h = h ^ (g >> 26) ^ g;
+ u32_t acc = seed;
+ u32_t ch;
+
+ while (count-- && (ch = *str++) != 0) {
+ acc ^= ch;
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
}
- return h;
+
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
+ acc ^= randbox[acc & 0xf];
+
+ return acc;
}
-static unsigned long hash_buf(const mem_t *ptr, cnum size)
+static u32_t hash_buf(const mem_t *ptr, cnum size, u32_t seed)
{
+ const u32_t *buf = coerce(const u32_t *, ptr);
int count = hash_str_limit;
- unsigned long h = 0;
+ u32_t acc = seed;
- for (; size >= 4 && count--; size -= 4, ptr += 4) {
- unsigned long el = (convert(unsigned long, ptr[0]) << 24 |
- convert(unsigned long, ptr[1]) << 16 |
- convert(unsigned long, ptr[2]) << 8 |
- convert(unsigned long, ptr[3]));
- unsigned long g;
- h = (h << 4) + el;
- g = h & 0x7C000000;
- h = h ^ (g >> 26) ^ g;
- ptr += 4;
+ for (; size >= sizeof *buf && count--; size -= sizeof *buf, buf++) {
+ u32_t in = *buf;
+ acc ^= in;
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
}
- if (count) {
- unsigned long el = 0;
- unsigned long g;
+ if (size != 0) {
+ const mem_t *tail = coerce(const mem_t *, ptr);
+ u32_t in = 0;
+
switch (size) {
- case 0:
- break;
case 3:
- el = *ptr++;
+ in |= convert(u32_t, tail[2]) << 16;
case 2:
- el = el << 8 | *ptr++;
+ in |= convert(u32_t, tail[1]) << 8;
case 1:
- el = el << 8 | *ptr++;
- h = (h << 4) + el;
- g = h & 0x7C000000;
- h = h ^ (g >> 26) ^ g;
- ptr += 4;
+ in |= convert(u32_t, tail[0]);
}
+
+ acc ^= in;
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
}
- return h;
+
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
+ acc ^= randbox[acc & 0xf];
+ acc = acc >> 1 | acc << (32 - 1);
+ acc ^= randbox[acc & 0xf];
+
+ return acc;
}
static cnum hash_double(double n)
@@ -174,7 +190,7 @@ static cnum hash_double(double n)
return h & NUM_MAX;
}
-cnum equal_hash(val obj, int *count)
+cnum equal_hash(val obj, int *count, ucnum seed)
{
if ((*count)-- <= 0)
return 0;
@@ -183,12 +199,13 @@ cnum equal_hash(val obj, int *count)
case NIL:
return NUM_MAX;
case LIT:
- return hash_c_str(litptr(obj)) & NUM_MAX;
+ return hash_c_str(litptr(obj), seed) & NUM_MAX;
case CONS:
- return (equal_hash(obj->c.car, count)
- + 32 * (equal_hash(obj->c.cdr, count) & (NUM_MAX / 16))) & NUM_MAX;
+ return (equal_hash(obj->c.car, count, seed)
+ + 32 * (equal_hash(obj->c.cdr, count, seed)
+ & (NUM_MAX / 16))) & NUM_MAX;
case STR:
- return hash_c_str(obj->st.str) & NUM_MAX;
+ return hash_c_str(obj->st.str, seed) & NUM_MAX;
case CHR:
return c_chr(obj) & NUM_MAX;
case NUM:
@@ -205,27 +222,28 @@ cnum equal_hash(val obj, int *count)
break;
case FUN:
return (coerce(cnum, obj->f.f.interp_fun)
- + equal_hash(obj->f.env, count)) & NUM_MAX;
+ + equal_hash(obj->f.env, count, seed)) & NUM_MAX;
case VEC:
{
val length = obj->v.vec[vec_length];
- cnum i, h = equal_hash(obj->v.vec[vec_length], count);
+ cnum i, h = equal_hash(obj->v.vec[vec_length], count, seed);
cnum len = c_num(length);
for (i = 0; i < len; i++) {
h = 32 * (h & (NUM_MAX / 16));
- h += equal_hash(obj->v.vec[i], count);
+ h += equal_hash(obj->v.vec[i], count, seed);
h &= NUM_MAX;
}
return h;
}
case LCONS:
- return (equal_hash(car(obj), count)
- + 32 * (equal_hash(cdr(obj), count) & (NUM_MAX / 16))) & NUM_MAX;
+ return (equal_hash(car(obj), count, seed)
+ + 32 * (equal_hash(cdr(obj), count, seed) &
+ (NUM_MAX / 16))) & NUM_MAX;
case LSTR:
lazy_str_force_upto(obj, num(hash_str_limit - 1));
- return equal_hash(obj->ls.prefix, count);
+ return equal_hash(obj->ls.prefix, count, seed);
case BGNUM:
return mp_hash(mp(obj)) & NUM_MAX;
case FLNUM:
@@ -235,14 +253,15 @@ cnum equal_hash(val obj, int *count)
if (obj->co.ops->equalsub) {
val sub = obj->co.ops->equalsub(obj);
if (sub)
- return equal_hash(sub, count);
+ return equal_hash(sub, count, seed);
}
- return obj->co.ops->hash(obj, count) & NUM_MAX;
+ return obj->co.ops->hash(obj, count, seed) & NUM_MAX;
case RNG:
- return (equal_hash(obj->rn.from, count)
- + 32 * (equal_hash(obj->rn.to, count) & (NUM_MAX / 16))) & NUM_MAX;
+ return (equal_hash(obj->rn.from, count, seed)
+ + 32 * (equal_hash(obj->rn.to, count, seed)
+ & (NUM_MAX / 16))) & NUM_MAX;
case BUF:
- return hash_buf(obj->b.data, c_num(obj->b.len));
+ return hash_buf(obj->b.data, c_num(obj->b.len), seed);
}
internal_error("unhandled case in equal function");
@@ -286,9 +305,16 @@ static cnum eql_hash(val obj, int *count)
abort();
}
-cnum cobj_eq_hash_op(val obj, int *count)
+static cnum eql_hash_op(val obj, int *count, ucnum seed)
+{
+ (void) seed;
+ return eql_hash(obj, count);
+}
+
+cnum cobj_eq_hash_op(val obj, int *count, ucnum seed)
{
(void) count;
+ (void) seed;
switch (sizeof (mem_t *)) {
case 4:
@@ -387,7 +413,7 @@ static val hash_equal_op(val left, val right)
return eq(pending, nil);
}
-static cnum hash_hash_op(val obj, int *count)
+static cnum hash_hash_op(val obj, int *count, ucnum seed)
{
cnum out = 0;
struct hash *h = coerce(struct hash *, obj->co.handle);
@@ -403,13 +429,13 @@ static cnum hash_hash_op(val obj, int *count)
out += coerce(cnum, h->hops) >> 5;
}
- out += equal_hash(h->userdata, count);
+ out += equal_hash(h->userdata, count, seed);
out &= NUM_MAX;
iter = hash_begin(obj);
while ((cell = hash_next(iter)) != nil) {
- out += equal_hash(cell, count);
+ out += equal_hash(cell, count, seed);
out &= NUM_MAX;
}
@@ -647,7 +673,7 @@ static val hash_aconsql_new_c(val key, cnum hash, loc new_p, loc list)
}
}
-static_def(struct hash_ops hash_eql_ops = hash_ops_init(eql_hash, eql,
+static_def(struct hash_ops hash_eql_ops = hash_ops_init(eql_hash_op, eql,
hash_assql,
hash_aconsql_new_c));
@@ -668,6 +694,7 @@ val make_hash(val weak_keys, val weak_vals, val equal_based)
val table = vector(mod, nil);
val hash = cobj(coerce(mem_t *, h), hash_s, &hash_ops);
+ h->seed = 0;
h->flags = convert(hash_flags_t, flags);
h->modulus = c_num(mod);
h->count = 0;
@@ -694,6 +721,7 @@ val make_similar_hash(val existing)
h->table = table;
h->userdata = ex->userdata;
+ h->seed = ex->seed;
h->flags = ex->flags;
h->usecount = 0;
h->hops = ex->hops;
@@ -743,7 +771,7 @@ val gethash_c(val hash, val key, loc new_p)
{
struct hash *h = coerce(struct hash *, cobj_handle(hash, hash_s));
int lim = hash_rec_limit;
- cnum hv = h->hops->hash_fun(key, &lim);
+ cnum hv = h->hops->hash_fun(key, &lim, h->seed);
loc pchain = vecref_l(h->table, num_fast(hv % h->modulus));
val old = deref(pchain);
val cell = h->hops->acons_new_c_fun(key, hv, new_p, pchain);
@@ -756,7 +784,7 @@ val gethash_e(val hash, val key)
{
struct hash *h = coerce(struct hash *, cobj_handle(hash, hash_s));
int lim = hash_rec_limit;
- cnum hv = h->hops->hash_fun(key, &lim);
+ cnum hv = h->hops->hash_fun(key, &lim, h->seed);
val chain = vecref(h->table, num_fast(hv % h->modulus));
return h->hops->assoc_fun(key, hv, chain);
}
@@ -813,7 +841,7 @@ val remhash(val hash, val key)
{
struct hash *h = coerce(struct hash *, cobj_handle(hash, hash_s));
int lim = hash_rec_limit;
- cnum hv = h->hops->hash_fun(key, &lim);
+ cnum hv = h->hops->hash_fun(key, &lim, h->seed);
val *pchain = valptr(vecref_l(h->table, num_fast(hv % h->modulus)));
val existing = h->hops->assoc_fun(key, hv, *pchain);
@@ -940,7 +968,7 @@ val hash_eql(val obj)
val hash_equal(val obj)
{
int lim = hash_rec_limit;
- return num_fast(equal_hash(obj, &lim));
+ return num_fast(equal_hash(obj, &lim, 0));
}
/*
diff --git a/hash.h b/hash.h
index 46a68e19..61d58424 100644
--- a/hash.h
+++ b/hash.h
@@ -27,7 +27,7 @@
extern val weak_keys_k, weak_vals_k, equal_based_k, eql_based_k, userdata_k;
-cnum equal_hash(val obj, int *count);
+cnum equal_hash(val obj, int *count, ucnum);
val make_hash(val weak_keys, val weak_vals, val equal_based);
val make_similar_hash(val existing);
val copy_hash(val existing);
diff --git a/lib.c b/lib.c
index 42facb48..2376177f 100644
--- a/lib.c
+++ b/lib.c
@@ -7851,10 +7851,10 @@ val cobj_equal_handle_op(val left, val right)
return (left->co.handle == right->co.handle) ? t : nil;
}
-cnum cobj_handle_hash_op(val obj, int *count)
+cnum cobj_handle_hash_op(val obj, int *count, ucnum seed)
{
mem_t *handle = obj->co.handle;
- return cobj_eq_hash_op(coerce(val, handle), count);
+ return cobj_eq_hash_op(coerce(val, handle), count, seed);
}
static struct cobj_ops cptr_ops = {
diff --git a/lib.h b/lib.h
index 1a81ed83..384812d2 100644
--- a/lib.h
+++ b/lib.h
@@ -244,7 +244,7 @@ struct cobj_ops {
void (*print)(val self, val stream, val pretty, struct strm_ctx *);
void (*destroy)(val self);
void (*mark)(val self);
- cnum (*hash)(val self, int *count);
+ cnum (*hash)(val self, int *count, ucnum seed);
val (*equalsub)(val self);
};
@@ -265,8 +265,8 @@ val cobj_equal_handle_op(val left, val right);
void cobj_destroy_stub_op(val);
void cobj_destroy_free_op(val);
void cobj_mark_op(val);
-cnum cobj_eq_hash_op(val, int *);
-cnum cobj_handle_hash_op(val, int *);
+cnum cobj_eq_hash_op(val, int *, ucnum);
+cnum cobj_handle_hash_op(val, int *, ucnum);
struct env {
obj_common;
diff --git a/struct.c b/struct.c
index f55c28f9..d1887f19 100644
--- a/struct.c
+++ b/struct.c
@@ -1492,16 +1492,16 @@ static val struct_inst_equal(val left, val right)
return t;
}
-static cnum struct_inst_hash(val obj, int *count)
+static cnum struct_inst_hash(val obj, int *count, ucnum seed)
{
struct struct_inst *si = coerce(struct struct_inst *, obj->co.handle);
struct struct_type *st = si->type;
- cnum nslots = st->nslots, sl, out = equal_hash(st->self, count);
+ cnum nslots = st->nslots, sl, out = equal_hash(st->self, count, seed);
check_init_lazy_struct(obj, si);
for (sl = 0; sl < nslots; sl++) {
- cnum hash = equal_hash(si->slot[sl], count);
+ cnum hash = equal_hash(si->slot[sl], count, seed);
out += hash;
out &= NUM_MAX;
}
diff --git a/tests/009/json.expected b/tests/009/json.expected
index 8c3fc4c6..6330a595 100644
--- a/tests/009/json.expected
+++ b/tests/009/json.expected
@@ -1,52 +1,54 @@
-AST: #H(() ("web-app" #H(() ("servlet-mapping" #H(() ("cofaxTools" "/tools/*") ("cofaxCDS" "/") ("cofaxAdmin" "/admin/*")
- ("cofaxEmail" "/cofaxutil/aemail/*") ("fileServlet" "/static/*")))
- ("servlet" #(#H(() ("servlet-class" "org.cofax.cds.CDSServlet") ("init-param" #H(() ("defaultFileTemplate" "articleTemplate.htm") ("configGlossary:installationAt" "Philadelphia, PA")
- ("templateOverridePath" "") ("dataStoreLogLevel" "debug") ("searchEngineListTemplate" "forSearchEnginesList.htm")
- ("dataStoreClass" "org.cofax.SqlDataStore") ("configGlossary:poweredBy" "Cofax")
- ("jspFileTemplate" "articleTemplate.jsp") ("cacheTemplatesTrack" 100.0)
- ("cacheTemplatesStore" 50.0) ("templateProcessorClass" "org.cofax.WysiwygTemplate")
- ("dataStoreUser" "sa") ("redirectionClass" "org.cofax.SqlRedirection")
- ("dataStoreConnUsageLimit" 100.0) ("dataStoreMaxConns" 100.0)
- ("jspListTemplate" "listTemplate.jsp") ("useJSP" :false) ("configGlossary:poweredByIcon" "/images/cofax.gif")
- ("templateLoaderClass" "org.cofax.FilesTemplateLoader") ("cacheTemplatesRefresh" 15.0)
- ("cachePagesDirtyRead" 10.0) ("searchEngineRobotsDb" "WEB-INF/robots.db")
- ("cachePagesStore" 100.0) ("dataStoreTestQuery" "SET NOCOUNT ON;select test='test';")
- ("configGlossary:adminEmail" "ksm@pobox.com") ("configGlossary:staticPath" "/content/static")
- ("dataStoreInitConns" 10.0) ("cachePagesTrack" 200.0) ("dataStorePassword" "dataStoreTestQuery")
- ("defaultListTemplate" "listTemplate.htm") ("dataStoreLogFile" "/usr/local/tomcat/logs/datastore.log")
- ("maxUrlLength" 500.0) ("dataStoreDriver" "com.microsoft.jdbc.sqlserver.SQLServerDriver")
- ("dataStoreName" "cofax") ("cachePackageTagsRefresh" 60.0) ("templatePath" "templates")
- ("dataStoreUrl" "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon")
- ("useDataStore" :true) ("cachePackageTagsTrack" 200.0) ("searchEngineFileTemplate" "forSearchEngines.htm")
- ("cachePackageTagsStore" 200.0) ("cachePagesRefresh" 10.0)))
- ("servlet-name" "cofaxCDS"))
- #H(() ("servlet-class" "org.cofax.cds.EmailServlet") ("init-param" #H(() ("mailHost" "mail1") ("mailHostOverride" "mail2")))
- ("servlet-name" "cofaxEmail"))
- #H(() ("servlet-class" "org.cofax.cds.AdminServlet") ("servlet-name" "cofaxAdmin"))
- #H(() ("servlet-class" "org.cofax.cds.FileServlet") ("servlet-name" "fileServlet"))
- #H(() ("servlet-class" "org.cofax.cms.CofaxToolsServlet") ("init-param" #H(() ("lookInContext" 1.0) ("removePageCache" "/content/admin/remove?cache=pages&id=")
- ("logMaxSize" "") ("dataLogMaxSize" "") ("removeTemplateCache" "/content/admin/remove?cache=templates&id=")
- ("dataLog" 1.0) ("logLocation" "/usr/local/tomcat/logs/CofaxTools.log")
- ("log" 1.0) ("adminGroupID" 4.0) ("templatePath" "toolstemplates/")
- ("betaServer" :true) ("dataLogLocation" "/usr/local/tomcat/logs/dataLog.log")
- ("fileTransferFolder" "/usr/local/tomcat/webapps/content/fileTransferFolder")))
- ("servlet-name" "cofaxTools"))))
- ("taglib" #H(() ("taglib-uri" "cofax.tld") ("taglib-location" "/WEB-INF/tlds/cofax.tld"))))))
+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/*"))))))
Unmatched junk: ""
AST: #("JSON Test Pattern pass1" #H(() ("object with 1 member" #("array with 1 element")))
- #H(()) #() -42.0 :true :false :null #H(() ("" 2.3456789012e76) ("digit" "0123456789") ("\\/\\\\\"쫾몾ꮘﳞ볚\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" "A key can be any string")
- ("null" :null) ("one" 1.0) ("E" 1.23456789e34) ("special" "`1~!@#$%^&*()_+-={':[,]}|;.</>?")
- ("e" 1.23456789e-13) ("comment" "// /* <!-- --") ("# -- --> */" " ")
- ("real" -9876.54321) ("backslash" "\\\\") ("array" #()) ("url" "http://www.JSON.org/")
- ("zero" 0.0) ("false" :false) ("space" " ") ("slash" "/ & \\/")
- ("address" "50 St. James Street") ("compact" #(1.0 2.0 3.0 4.0 5.0 6.0 7.0))
- ("object" #H(())) ("quote" "\"") ("jsontext" "{\"object with 1 member\":[\"array with 1 element\"]}")
- ("true" :true) ("integer" 1234567890.0) ("ALPHA" "ABCDEFGHIJKLMNOPQRSTUVWYZ")
- ("quotes" "&#34; \" %22 0x22 034 &#x22;") ("hex" "ģ䕧覫췯ꯍ")
- ("0123456789" "digit") ("controls" "\b\f\n\r\t") ("alpha" "abcdefghijklmnopqrstuvwyz")
- (" s p a c e d " #(1.0 2.0 3.0 4.0 5.0 6.0 7.0)))
+ #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))
0.5 98.6 99.44 1066.0 10.0 1.0 0.1 1.0 2.0 2.0 "rosebud")
Unmatched junk: ""