diff --git a/TODO.FACTOR.txt b/TODO.FACTOR.txt index 0b904095d8..4e0b1a6c55 100644 --- a/TODO.FACTOR.txt +++ b/TODO.FACTOR.txt @@ -44,8 +44,6 @@ FFI: - add a socket timeout - fix error postoning -- not all errors thrown by i/o code are postponed -- sbuf-hashcode -- vector-hashcode - some way to run httpd from command line + bignums: diff --git a/factor/FactorArray.java b/factor/FactorArray.java index ea686b2059..8010940a9f 100644 --- a/factor/FactorArray.java +++ b/factor/FactorArray.java @@ -204,6 +204,20 @@ public class FactorArray implements FactorExternalizable, PublicCloneable } } //}}} + //{{{ hashCode() method + public int hashCode() + { + int hashCode = 0; + for(int i = 0; i < Math.min(top,4); i++) + { + Object obj = stack[i]; + if(obj != null) + hashCode ^= obj.hashCode(); + } + + return hashCode; + } //}}} + //{{{ equals() method public boolean equals(Object obj) { diff --git a/library/cross-compiler.factor b/library/cross-compiler.factor index ce22a59505..2b64d12c85 100644 --- a/library/cross-compiler.factor +++ b/library/cross-compiler.factor @@ -80,6 +80,7 @@ IN: strings DEFER: str= DEFER: str-hashcode DEFER: sbuf= +DEFER: sbuf-hashcode DEFER: sbuf-clone IN: files @@ -221,6 +222,7 @@ IN: image sbuf-reverse sbuf-clone sbuf= + sbuf-hashcode arithmetic-type number? >fixnum diff --git a/library/platform/native/kernel.factor b/library/platform/native/kernel.factor index b12a447e49..87bb0808c9 100644 --- a/library/platform/native/kernel.factor +++ b/library/platform/native/kernel.factor @@ -67,9 +67,9 @@ USE: vectors [ drop 0 ] [ drop 0 ] [ drop 0 ] - [ drop 0 ] + [ vector-hashcode ] [ str-hashcode ] - [ drop 0 ] + [ sbuf-hashcode ] [ drop 0 ] [ >fixnum ] [ >fixnum ] diff --git a/library/platform/native/primitives.factor b/library/platform/native/primitives.factor index b8009cc93b..9c80ae3ba3 100644 --- a/library/platform/native/primitives.factor +++ b/library/platform/native/primitives.factor @@ -75,6 +75,7 @@ USE: words [ sbuf-reverse | " sbuf -- " ] [ sbuf-clone | " sbuf -- sbuf " ] [ sbuf= | " sbuf sbuf -- ? " ] + [ sbuf-hashcode | " sbuf -- n " ] [ arithmetic-type | " n n -- type " ] [ number? | " obj -- ? " ] [ >fixnum | " n -- fixnum " ] diff --git a/library/platform/native/vectors.factor b/library/platform/native/vectors.factor index 7508e6743c..5fead95f81 100644 --- a/library/platform/native/vectors.factor +++ b/library/platform/native/vectors.factor @@ -66,3 +66,11 @@ USE: stack ] [ 2drop f ] ifte ; + +: ?vector-nth ( n vec -- obj/f ) + 2dup vector-length >= [ 2drop f ] [ vector-nth ] ifte ; + +: vector-hashcode ( vec -- n ) + 0 swap 4 [ + over ?vector-nth hashcode rot bitxor swap + ] times* drop ; diff --git a/library/test/httpd/html.factor b/library/test/httpd/html.factor index cb6303eb68..2ab1a8cf6d 100644 --- a/library/test/httpd/html.factor +++ b/library/test/httpd/html.factor @@ -19,7 +19,7 @@ USE: stack ] with-scope ] unit-test -[ "" ] +[ "" ] [ [ "" diff --git a/library/test/math/bitops.factor b/library/test/math/bitops.factor index fd39b8c992..406611748a 100644 --- a/library/test/math/bitops.factor +++ b/library/test/math/bitops.factor @@ -51,6 +51,6 @@ USE: lists [ 12 ] [ 11 4 align ] unit-test [ 12 ] [ 12 4 align ] unit-test -[ 12 ] [ 10 2 align ] unit-test +[ 10 ] [ 10 2 align ] unit-test [ 14 ] [ 13 2 align ] unit-test [ 11 ] [ 11 1 align ] unit-test diff --git a/library/test/sbuf.factor b/library/test/sbuf.factor new file mode 100644 index 0000000000..6c3e5a3811 --- /dev/null +++ b/library/test/sbuf.factor @@ -0,0 +1,29 @@ +IN: scratchpad +USE: combinators +USE: errors +USE: kernel +USE: logic +USE: math +USE: namespaces +USE: stack +USE: strings +USE: test + +native? [ + [ t ] [ "Foo" str>sbuf "Foo" str>sbuf = ] unit-test + [ f ] [ "Foo" str>sbuf "Foob" str>sbuf = ] unit-test + [ f ] [ 34 "Foo" str>sbuf = ] unit-test + + [ "Hello" ] [ + 100 "buf" set + "Hello" "buf" get sbuf-append + "buf" get clone "buf-clone" set + "World" "buf-clone" get sbuf-append + "buf" get sbuf>str + ] unit-test + + [ t ] [ + "Hello world" str>sbuf hashcode + "Hello world" hashcode = + ] unit-test +] when diff --git a/library/test/strings.factor b/library/test/strings.factor index 07fa8e6ccc..5c98bc8458 100644 --- a/library/test/strings.factor +++ b/library/test/strings.factor @@ -88,20 +88,6 @@ unit-test [ "fedcba" ] [ "abcdef" str-reverse ] unit-test [ "edcba" ] [ "abcde" str-reverse ] unit-test -native? [ - [ t ] [ "Foo" str>sbuf "Foo" str>sbuf = ] unit-test - [ f ] [ "Foo" str>sbuf "Foob" str>sbuf = ] unit-test - [ f ] [ 34 "Foo" str>sbuf = ] unit-test - - [ "Hello" ] [ - 100 "buf" set - "Hello" "buf" get sbuf-append - "buf" get clone "buf-clone" set - "World" "buf-clone" get sbuf-append - "buf" get sbuf>str - ] unit-test -] when - [ f ] [ [ 0 10 "hello" substring ] [ not ] catch ] unit-test [ [ "hell" "o wo" "rld" ] ] [ 4 "hello world" split-n ] unit-test diff --git a/library/test/test.factor b/library/test/test.factor index 3304914651..6a2c7f92d1 100644 --- a/library/test/test.factor +++ b/library/test/test.factor @@ -72,6 +72,7 @@ USE: unparser "errors" "hashtables" "strings" + "sbuf" "namespaces/namespaces" "files" "format" diff --git a/library/test/vectors.factor b/library/test/vectors.factor index 33098e517d..cd81ae9a7e 100644 --- a/library/test/vectors.factor +++ b/library/test/vectors.factor @@ -27,3 +27,8 @@ USE: vectors [ list>vector [ 3 > ] vector-all? ] test-word [ t ] [ [ ] ] [ list>vector [ 3 > ] vector-all? ] test-word + +[ t ] [ { } hashcode { } hashcode = ] unit-test +[ t ] [ { 1 2 3 } hashcode { 1 2 3 } hashcode = ] unit-test +[ t ] [ { 1 { 2 } 3 } hashcode { 1 { 2 } 3 } hashcode = ] unit-test +[ t ] [ { } hashcode { } hashcode = ] unit-test diff --git a/native/primitives.c b/native/primitives.c index 3489be5e71..de8e9fb4ca 100644 --- a/native/primitives.c +++ b/native/primitives.c @@ -34,6 +34,7 @@ XT primitives[] = { primitive_sbuf_reverse, primitive_sbuf_clone, primitive_sbuf_eq, + primitive_sbuf_hashcode, primitive_arithmetic_type, primitive_numberp, primitive_to_fixnum, diff --git a/native/primitives.h b/native/primitives.h index 1aa49ac281..bf3cca526c 100644 --- a/native/primitives.h +++ b/native/primitives.h @@ -1,4 +1,4 @@ extern XT primitives[]; -#define PRIMITIVE_COUNT 192 +#define PRIMITIVE_COUNT 193 CELL primitive_to_xt(CELL primitive); diff --git a/native/relocate.c b/native/relocate.c index 9adcd5f890..917288b82a 100644 --- a/native/relocate.c +++ b/native/relocate.c @@ -20,7 +20,7 @@ void relocate_object() fixup_vector((VECTOR*)relocating); break; case STRING_TYPE: - hash_string((STRING*)relocating); + rehash_string((STRING*)relocating); break; case SBUF_TYPE: fixup_sbuf((SBUF*)relocating); diff --git a/native/sbuf.c b/native/sbuf.c index 80a391b0a3..9c1cefa9a8 100644 --- a/native/sbuf.c +++ b/native/sbuf.c @@ -100,7 +100,7 @@ void primitive_sbuf_to_string(void) { SBUF* sbuf = untag_sbuf(dpeek()); STRING* s = string_clone(sbuf->string,sbuf->top); - hash_string(s); + rehash_string(s); drepl(tag_object(s)); } @@ -120,7 +120,9 @@ void primitive_sbuf_clone(void) bool sbuf_eq(SBUF* s1, SBUF* s2) { - if(s1->top == s2->top) + if(s1 == s2) + return true; + else if(s1->top == s2->top) return (string_compare_head(s1->string,s2->string,s1->top) == 0); else return false; @@ -136,6 +138,12 @@ void primitive_sbuf_eq(void) dpush(F); } +void primitive_sbuf_hashcode(void) +{ + SBUF* sbuf = untag_sbuf(dpop()); + dpush(tag_fixnum(hash_string(sbuf->string,sbuf->top))); +} + void fixup_sbuf(SBUF* sbuf) { sbuf->string = fixup_untagged_string(sbuf->string); diff --git a/native/sbuf.h b/native/sbuf.h index 0c40cc95ca..02d760bcce 100644 --- a/native/sbuf.h +++ b/native/sbuf.h @@ -29,5 +29,6 @@ void primitive_sbuf_reverse(void); void primitive_sbuf_clone(void); bool sbuf_eq(SBUF* s1, SBUF* s2); void primitive_sbuf_eq(void); +void primitive_sbuf_hashcode(void); void fixup_sbuf(SBUF* sbuf); void collect_sbuf(SBUF* sbuf); diff --git a/native/string.c b/native/string.c index a3102a9970..42a9fcd4c8 100644 --- a/native/string.c +++ b/native/string.c @@ -13,14 +13,20 @@ STRING* allot_string(FIXNUM capacity) } /* call this after constructing a string */ -/* uses same algorithm as java.lang.String for compatibility */ -void hash_string(STRING* str) +/* uses same algorithm as java.lang.String for compatibility with +images generated from Java Factor. */ +FIXNUM hash_string(STRING* str, FIXNUM len) { FIXNUM hash = 0; CELL i; - for(i = 0; i < str->capacity; i++) + for(i = 0; i < len; i++) hash = 31*hash + string_nth(str,i); - str->hashcode = hash; + return hash; +} + +void rehash_string(STRING* str) +{ + str->hashcode = hash_string(str,str->capacity); } /* untagged */ @@ -33,7 +39,7 @@ STRING* string(FIXNUM capacity, CELL fill) for(i = 0; i < capacity; i++) cput(SREF(string,i),fill); - hash_string(string); + rehash_string(string); return string; } @@ -66,7 +72,7 @@ STRING* from_c_string(const BYTE* c_string) c_string++; } - hash_string(s); + rehash_string(s); return s; } @@ -158,7 +164,9 @@ void primitive_string_compare(void) bool string_eq(STRING* s1, STRING* s2) { - if(s1->hashcode != s2->hashcode) + if(s1 == s2) + return true; + else if(s1->hashcode != s2->hashcode) return false; else return (string_compare(s1,s2) == 0); @@ -258,7 +266,7 @@ INLINE STRING* substring(CELL start, CELL end, STRING* string) memcpy(result + 1, (void*)((CELL)(string + 1) + CHARS * start), CHARS * (end - start)); - hash_string(result); + rehash_string(result); return result; } @@ -300,7 +308,7 @@ void primitive_string_reverse(void) STRING* s = untag_string(dpeek()); s = string_clone(s,s->capacity); string_reverse(s,s->capacity); - hash_string(s); + rehash_string(s); drepl(tag_object(s)); } diff --git a/native/string.h b/native/string.h index 7191468b6a..146655aab4 100644 --- a/native/string.h +++ b/native/string.h @@ -14,7 +14,8 @@ INLINE STRING* untag_string(CELL tagged) STRING* allot_string(FIXNUM capacity); STRING* string(FIXNUM capacity, CELL fill); -void hash_string(STRING* str); +FIXNUM hash_string(STRING* str, FIXNUM len); +void rehash_string(STRING* str); STRING* grow_string(STRING* string, FIXNUM capacity, CHAR fill); BYTE* to_c_string(STRING* s); void box_c_string(const BYTE* c_string);