From b03c41736332b06815ef76da1abf2aa3796d540a Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Tue, 10 Nov 2015 12:48:49 +0100 Subject: [PATCH 1/4] Implement BB_new_from_str --- runtime/core/Clownfish/ByteBuf.c | 12 ++++++++++++ runtime/core/Clownfish/ByteBuf.cfh | 11 ++++++++++- runtime/core/Clownfish/Test/TestByteBuf.c | 14 +++++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/runtime/core/Clownfish/ByteBuf.c b/runtime/core/Clownfish/ByteBuf.c index 210ed180..8eed5235 100644 --- a/runtime/core/Clownfish/ByteBuf.c +++ b/runtime/core/Clownfish/ByteBuf.c @@ -26,6 +26,7 @@ #include "Clownfish/ByteBuf.h" #include "Clownfish/Blob.h" #include "Clownfish/Err.h" +#include "Clownfish/String.h" #include "Clownfish/Util/Memory.h" static void @@ -50,6 +51,17 @@ BB_init(ByteBuf *self, size_t capacity) { ByteBuf* BB_new_bytes(const void *bytes, size_t size) { ByteBuf *self = (ByteBuf*)Class_Make_Obj(BYTEBUF); + return BB_init_bytes(self, bytes, size); +} + +ByteBuf* +BB_new_from_str(String *string) { + ByteBuf *self = (ByteBuf*)Class_Make_Obj(BYTEBUF); + return BB_init_bytes(self, Str_Get_Ptr8(string), Str_Get_Size(string)); +} + +ByteBuf* +BB_init_bytes(ByteBuf *self, const void *bytes, size_t size) { BB_init(self, size); memcpy(self->buf, bytes, size); self->size = size; diff --git a/runtime/core/Clownfish/ByteBuf.cfh b/runtime/core/Clownfish/ByteBuf.cfh index 02357410..dbf170d6 100644 --- a/runtime/core/Clownfish/ByteBuf.cfh +++ b/runtime/core/Clownfish/ByteBuf.cfh @@ -36,11 +36,20 @@ final class Clownfish::ByteBuf nickname BB inherits Clownfish::Obj { init(ByteBuf *self, size_t capacity); /** Return a pointer to a new ByteBuf which holds a copy of the passed-in - * string. + * bytes. */ inert incremented ByteBuf* new_bytes(const void *bytes, size_t size); + /** Return a pointer to a new ByteBuf which holds a copy of the passed-in + * String. + */ + inert incremented ByteBuf* + new_from_str(String *string); + + inert ByteBuf* + init_bytes(ByteBuf *self, const void *bytes, size_t size); + /** Return a pointer to a new ByteBuf which assumes ownership of the * passed-in string. */ diff --git a/runtime/core/Clownfish/Test/TestByteBuf.c b/runtime/core/Clownfish/Test/TestByteBuf.c index 1fe41b87..937bbc42 100644 --- a/runtime/core/Clownfish/Test/TestByteBuf.c +++ b/runtime/core/Clownfish/Test/TestByteBuf.c @@ -27,12 +27,23 @@ #include "Clownfish/TestHarness/TestUtils.h" #include "Clownfish/Blob.h" #include "Clownfish/Class.h" +#include "Clownfish/String.h" TestByteBuf* TestBB_new() { return (TestByteBuf*)Class_Make_Obj(TESTBYTEBUF); } +static void +test_new_from_str(TestBatchRunner *runner) { + String *string = Str_newf("foo"); + ByteBuf *bb = BB_new_from_str(string); + const char *buf = BB_Get_Buf(bb); + size_t size = BB_Get_Size(bb); + TEST_INT_EQ(runner, size, 3, "size after new_from_str"); + TEST_TRUE(runner, memcmp(buf, "foo", 3) == 0, "buf after new_from_str"); +} + static void test_Equals(TestBatchRunner *runner) { ByteBuf *wanted = BB_new_bytes("foo", 4); // Include terminating NULL. @@ -142,7 +153,8 @@ test_Cat(TestBatchRunner *runner) { void TestBB_Run_IMP(TestByteBuf *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 19); + TestBatchRunner_Plan(runner, (TestBatch*)self, 21); + test_new_from_str(runner); test_Equals(runner); test_Grow(runner); test_Clone(runner); From 0494a41cd3250a6defb2b47c46220cff1fd94c80 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Tue, 10 Nov 2015 12:54:54 +0100 Subject: [PATCH 2/4] Make BB_Mimic work with Strings --- runtime/core/Clownfish/ByteBuf.c | 13 +++++++++++-- runtime/core/Clownfish/Test/TestByteBuf.c | 7 ++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/runtime/core/Clownfish/ByteBuf.c b/runtime/core/Clownfish/ByteBuf.c index 8eed5235..1b22cfb3 100644 --- a/runtime/core/Clownfish/ByteBuf.c +++ b/runtime/core/Clownfish/ByteBuf.c @@ -151,8 +151,17 @@ BB_Mimic_Bytes_IMP(ByteBuf *self, const void *bytes, size_t size) { void BB_Mimic_IMP(ByteBuf *self, Obj *other) { - ByteBuf *twin = (ByteBuf*)CERTIFY(other, BYTEBUF); - SI_mimic_bytes(self, twin->buf, twin->size); + if (Obj_is_a(other, BYTEBUF)) { + ByteBuf *twin = (ByteBuf*)other; + SI_mimic_bytes(self, twin->buf, twin->size); + } + else if (Obj_is_a(other, STRING)) { + String *string = (String*)other; + SI_mimic_bytes(self, Str_Get_Ptr8(string), Str_Get_Size(string)); + } + else { + THROW(ERR, "ByteBuf can't mimic %o", Obj_get_class_name(other)); + } } static CFISH_INLINE void diff --git a/runtime/core/Clownfish/Test/TestByteBuf.c b/runtime/core/Clownfish/Test/TestByteBuf.c index 937bbc42..ff9c8b9b 100644 --- a/runtime/core/Clownfish/Test/TestByteBuf.c +++ b/runtime/core/Clownfish/Test/TestByteBuf.c @@ -129,6 +129,11 @@ test_Mimic(TestBatchRunner *runner) { BB_Mimic(b, (Obj*)a); TEST_TRUE(runner, BB_Equals(a, (Obj*)b), "Mimic"); + String *string = Str_newf("baz"); + BB_Mimic(b, (Obj*)string); + DECREF(string); + TEST_TRUE(runner, BB_Equals_Bytes(b, "baz", 3), "Mimic String"); + DECREF(a); DECREF(b); } @@ -153,7 +158,7 @@ test_Cat(TestBatchRunner *runner) { void TestBB_Run_IMP(TestByteBuf *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 21); + TestBatchRunner_Plan(runner, (TestBatch*)self, 22); test_new_from_str(runner); test_Equals(runner); test_Grow(runner); From 7508106e887117500cc8bbb273e0f065cc71a85e Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Tue, 10 Nov 2015 13:04:48 +0100 Subject: [PATCH 3/4] Implement Str_new_from_bb --- runtime/core/Clownfish/String.c | 12 ++++++++++++ runtime/core/Clownfish/String.cfh | 12 ++++++++++++ runtime/core/Clownfish/Test/TestString.c | 16 +++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/runtime/core/Clownfish/String.c b/runtime/core/Clownfish/String.c index 4daaa83c..0d19ae48 100644 --- a/runtime/core/Clownfish/String.c +++ b/runtime/core/Clownfish/String.c @@ -26,6 +26,7 @@ #include "Clownfish/Class.h" #include "Clownfish/String.h" +#include "Clownfish/ByteBuf.h" #include "Clownfish/CharBuf.h" #include "Clownfish/Err.h" #include "Clownfish/Util/Memory.h" @@ -65,6 +66,17 @@ Str_new_from_trusted_utf8(const char *utf8, size_t size) { return Str_init_from_trusted_utf8(self, utf8, size); } +String* +Str_new_from_bb(ByteBuf *bb) { + return Str_new_from_utf8(BB_Get_Buf(bb), BB_Get_Size(bb)); +} + +String* +Str_new_from_trusted_bb(ByteBuf *bb) { + String *self = (String*)Class_Make_Obj(STRING); + return Str_init_from_trusted_utf8(self, BB_Get_Buf(bb), BB_Get_Size(bb)); +} + String* Str_init_from_trusted_utf8(String *self, const char *utf8, size_t size) { // Allocate. diff --git a/runtime/core/Clownfish/String.cfh b/runtime/core/Clownfish/String.cfh index 284e6ec9..bcc0392c 100644 --- a/runtime/core/Clownfish/String.cfh +++ b/runtime/core/Clownfish/String.cfh @@ -49,6 +49,18 @@ public final class Clownfish::String nickname Str public inert incremented String* new_from_trusted_utf8(const char *utf8, size_t size); + /** Return a String which holds a copy of the UTF-8 character data in + * the supplied ByteBuf after checking for validity. + */ + public inert incremented String* + new_from_bb(ByteBuf *bb); + + /** Return a String which holds a copy of the UTF-8 character data in + * the supplied ByteBuf, skipping validity checks. + */ + public inert incremented String* + new_from_trusted_bb(ByteBuf *bb); + /** Initialize a String which holds a copy of the supplied UTF-8 character * data, skipping validity checks. */ diff --git a/runtime/core/Clownfish/Test/TestString.c b/runtime/core/Clownfish/Test/TestString.c index c32dbd1a..0f83a064 100644 --- a/runtime/core/Clownfish/Test/TestString.c +++ b/runtime/core/Clownfish/Test/TestString.c @@ -24,6 +24,7 @@ #include "Clownfish/String.h" #include "Clownfish/Boolean.h" +#include "Clownfish/ByteBuf.h" #include "Clownfish/CharBuf.h" #include "Clownfish/Test.h" #include "Clownfish/TestHarness/TestBatchRunner.h" @@ -112,6 +113,19 @@ test_new(TestBatchRunner *runner) { "Str_new_from_char"); DECREF(smiley_str); } + + { + ByteBuf *bb = BB_new_bytes(chars, sizeof(chars) - 1); + String *string = Str_new_from_bb(bb); + TEST_TRUE(runner, Str_Equals_Utf8(string, chars, sizeof(chars) - 1), + "Str_new_from_bb"); + DECREF(string); + string = Str_new_from_trusted_bb(bb); + TEST_TRUE(runner, Str_Equals_Utf8(string, chars, sizeof(chars) - 1), + "Str_new_from_trusted_bb"); + DECREF(string); + DECREF(bb); + } } static void @@ -693,7 +707,7 @@ test_iterator_substring(TestBatchRunner *runner) { void TestStr_Run_IMP(TestString *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 138); + TestBatchRunner_Plan(runner, (TestBatch*)self, 140); test_new(runner); test_Cat(runner); test_Clone(runner); From 7566eb0c97ab4820e470f1ada166c5796ca4eccd Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Tue, 10 Nov 2015 13:11:43 +0100 Subject: [PATCH 4/4] Implement CB_Clear --- runtime/core/Clownfish/CharBuf.c | 5 +++++ runtime/core/Clownfish/CharBuf.cfh | 5 +++++ runtime/core/Clownfish/Test/TestCharBuf.c | 14 +++++++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/runtime/core/Clownfish/CharBuf.c b/runtime/core/Clownfish/CharBuf.c index e5e3aa2c..6e549101 100644 --- a/runtime/core/Clownfish/CharBuf.c +++ b/runtime/core/Clownfish/CharBuf.c @@ -388,6 +388,11 @@ CB_Cat_IMP(CharBuf *self, String *string) { SI_cat_utf8(self, string->ptr, string->size); } +void +CB_Clear_IMP(CharBuf *self) { + self->size = 0; +} + void CB_Set_Size_IMP(CharBuf *self, size_t size) { if (size >= self->cap) { diff --git a/runtime/core/Clownfish/CharBuf.cfh b/runtime/core/Clownfish/CharBuf.cfh index 788c0d4e..0112ae80 100644 --- a/runtime/core/Clownfish/CharBuf.cfh +++ b/runtime/core/Clownfish/CharBuf.cfh @@ -117,6 +117,11 @@ final class Clownfish::CharBuf nickname CB char* Grow(CharBuf *self, size_t size); + /** Clear the CharBuf. + */ + void + Clear(CharBuf *self); + /** Set the CharBuf's `size` attribute. */ void diff --git a/runtime/core/Clownfish/Test/TestCharBuf.c b/runtime/core/Clownfish/Test/TestCharBuf.c index 30d8c11a..5763e99a 100644 --- a/runtime/core/Clownfish/Test/TestCharBuf.c +++ b/runtime/core/Clownfish/Test/TestCharBuf.c @@ -323,9 +323,20 @@ test_vcatf_x32(TestBatchRunner *runner) { DECREF(got); } +static void +test_Clear(TestBatchRunner *runner) { + CharBuf *cb = S_get_cb("foo"); + CB_Clear(cb); + CB_Cat_Utf8(cb, "bar", 3); + String *string = CB_Yield_String(cb); + TEST_TRUE(runner, Str_Equals_Utf8(string, "bar", 3), "Clear"); + DECREF(string); + DECREF(cb); +} + void TestCB_Run_IMP(TestCharBuf *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 26); + TestBatchRunner_Plan(runner, (TestBatch*)self, 27); test_new(runner); test_vcatf_percent(runner); test_vcatf_s(runner); @@ -344,5 +355,6 @@ TestCB_Run_IMP(TestCharBuf *self, TestBatchRunner *runner) { test_Cat(runner); test_Mimic_and_Clone(runner); test_Get_Ptr8(runner); + test_Clear(runner); }