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);