Repository: lucy-clownfish Updated Branches: refs/heads/master aab014633 -> 3e654d21b
Initial Blob implementation Copied from ByteBuf leaving out the mutable stuff. Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/1b1789a2 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/1b1789a2 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/1b1789a2 Branch: refs/heads/master Commit: 1b1789a2e4d6675bf94693d93b320ea911b82028 Parents: aab0146 Author: Nick Wellnhofer <[email protected]> Authored: Mon May 4 15:25:33 2015 +0200 Committer: Nick Wellnhofer <[email protected]> Committed: Tue May 5 11:15:07 2015 +0200 ---------------------------------------------------------------------- runtime/core/Clownfish/Blob.c | 136 ++++++++++++++++++++++++++ runtime/core/Clownfish/Blob.cfh | 81 +++++++++++++++ runtime/core/Clownfish/Test.c | 2 + runtime/core/Clownfish/Test/TestBlob.c | 114 +++++++++++++++++++++ runtime/core/Clownfish/Test/TestBlob.cfh | 28 ++++++ runtime/perl/t/core/021-blob.t | 23 +++++ 6 files changed, 384 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1b1789a2/runtime/core/Clownfish/Blob.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Blob.c b/runtime/core/Clownfish/Blob.c new file mode 100644 index 0000000..d013399 --- /dev/null +++ b/runtime/core/Clownfish/Blob.c @@ -0,0 +1,136 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define C_CFISH_BLOB +#define CFISH_USE_SHORT_NAMES + +#include <string.h> + +#include "Clownfish/Class.h" +#include "Clownfish/Blob.h" +#include "Clownfish/Err.h" +#include "Clownfish/Util/Memory.h" + +Blob* +Blob_new(const char *buf, size_t size) { + Blob *self = (Blob*)Class_Make_Obj(BLOB); + return Blob_init(self, buf, size); +} + +Blob* +Blob_init(Blob *self, const char *buf, size_t size) { + char *copy = (char*)MALLOCATE(size); + memcpy(copy, buf, size); + + self->buf = copy; + self->size = size; + self->owns_buf = true; + + return self; +} + +Blob* +Blob_new_steal(char *buf, size_t size) { + Blob *self = (Blob*)Class_Make_Obj(BLOB); + return Blob_init_steal(self, buf, size); +} + +Blob* +Blob_init_steal(Blob *self, char *buf, size_t size) { + self->buf = buf; + self->size = size; + self->owns_buf = true; + + return self; +} + +Blob* +Blob_new_wrap(const char *buf, size_t size) { + Blob *self = (Blob*)Class_Make_Obj(BLOB); + return Blob_init_wrap(self, buf, size); +} + +Blob* +Blob_init_wrap(Blob *self, const char *buf, size_t size) { + self->buf = buf; + self->size = size; + self->owns_buf = false; + + return self; +} + +void +Blob_Destroy_IMP(Blob *self) { + if (self->owns_buf) { FREEMEM((char*)self->buf); } + SUPER_DESTROY(self, BLOB); +} + +Blob* +Blob_Clone_IMP(Blob *self) { + return (Blob*)INCREF(self); +} + +const char* +Blob_Get_Buf_IMP(Blob *self) { + return self->buf; +} + +size_t +Blob_Get_Size_IMP(Blob *self) { + return self->size; +} + +static CFISH_INLINE bool +SI_equals_bytes(Blob *self, const void *bytes, size_t size) { + if (self->size != size) { return false; } + return (memcmp(self->buf, bytes, self->size) == 0); +} + +bool +Blob_Equals_IMP(Blob *self, Obj *other) { + Blob *const twin = (Blob*)other; + if (twin == self) { return true; } + if (!Obj_Is_A(other, BLOB)) { return false; } + return SI_equals_bytes(self, twin->buf, twin->size); +} + +bool +Blob_Equals_Bytes_IMP(Blob *self, const void *bytes, size_t size) { + return SI_equals_bytes(self, bytes, size); +} + +int +Blob_compare(const void *va, const void *vb) { + Blob *a = *(Blob**)va; + Blob *b = *(Blob**)vb; + const size_t size = a->size < b->size ? a->size : b->size; + + int32_t comparison = memcmp(a->buf, b->buf, size); + + if (comparison == 0 && a->size != b->size) { + comparison = a->size < b->size ? -1 : 1; + } + + return comparison; +} + +int32_t +Blob_Compare_To_IMP(Blob *self, Obj *other) { + CERTIFY(other, BLOB); + return Blob_compare(&self, &other); +} + + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1b1789a2/runtime/core/Clownfish/Blob.cfh ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Blob.cfh b/runtime/core/Clownfish/Blob.cfh new file mode 100644 index 0000000..77a31ed --- /dev/null +++ b/runtime/core/Clownfish/Blob.cfh @@ -0,0 +1,81 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +parcel Clownfish; + +/** + * Immutable buffer holding arbitrary bytes. + */ + +class Clownfish::Blob inherits Clownfish::Obj { + + const char *buf; + size_t size; + bool owns_buf; + + inert incremented Blob* + new(const char *buf, size_t size); + + inert Blob* + init(Blob *self, const char *buf, size_t size); + + inert incremented Blob* + new_steal(char *buf, size_t size); + + inert Blob* + init_steal(Blob *self, char *buf, size_t size); + + inert incremented Blob* + new_wrap(const char *buf, size_t size); + + inert Blob* + init_wrap(Blob *self, const char *buf, size_t size); + + /** Lexical comparison of two Blobs, with level of indirection set to + * please qsort and friends. + */ + inert int + compare(const void *va, const void *vb); + + /** Accessor for "size" member. + */ + public size_t + Get_Size(Blob *self); + + /** Accessor for raw internal buffer. + */ + public const char* + Get_Buf(Blob *self); + + /** Test whether the Blob matches the passed-in bytes. + */ + public bool + Equals_Bytes(Blob *self, const void *bytes, size_t size); + + public int32_t + Compare_To(Blob *self, Obj *other); + + public incremented Blob* + Clone(Blob *self); + + public void + Destroy(Blob *self); + + public bool + Equals(Blob *self, Obj *other); +} + + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1b1789a2/runtime/core/Clownfish/Test.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Test.c b/runtime/core/Clownfish/Test.c index 03c91a9..cef3508 100644 --- a/runtime/core/Clownfish/Test.c +++ b/runtime/core/Clownfish/Test.c @@ -22,6 +22,7 @@ #include "Clownfish/TestHarness/TestBatch.h" #include "Clownfish/TestHarness/TestSuite.h" +#include "Clownfish/Test/TestBlob.h" #include "Clownfish/Test/TestByteBuf.h" #include "Clownfish/Test/TestString.h" #include "Clownfish/Test/TestCharBuf.h" @@ -47,6 +48,7 @@ Test_create_test_suite() { TestSuite_Add_Batch(suite, (TestBatch*)TestHashIterator_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestObj_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestErr_new()); + TestSuite_Add_Batch(suite, (TestBatch*)TestBlob_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestBB_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestStr_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestCB_new()); http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1b1789a2/runtime/core/Clownfish/Test/TestBlob.c ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Test/TestBlob.c b/runtime/core/Clownfish/Test/TestBlob.c new file mode 100644 index 0000000..e64e49a --- /dev/null +++ b/runtime/core/Clownfish/Test/TestBlob.c @@ -0,0 +1,114 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define CFISH_USE_SHORT_NAMES +#define TESTCFISH_USE_SHORT_NAMES + +#include "Clownfish/Test/TestBlob.h" + +#include "Clownfish/Blob.h" +#include "Clownfish/Test.h" +#include "Clownfish/TestHarness/TestBatchRunner.h" +#include "Clownfish/TestHarness/TestUtils.h" +#include "Clownfish/Class.h" + +TestBlob* +TestBlob_new() { + return (TestBlob*)Class_Make_Obj(TESTBLOB); +} + +static void +test_Equals(TestBatchRunner *runner) { + Blob *blob = Blob_new("foo", 4); // Include terminating NULL. + + { + Blob *other = Blob_new("foo", 4); + TEST_TRUE(runner, Blob_Equals(blob, (Obj*)other), "Equals"); + DECREF(other); + } + + { + Blob *other = Blob_new("foo", 3); + TEST_FALSE(runner, Blob_Equals(blob, (Obj*)other), + "Different size spoils Equals"); + DECREF(other); + } + + { + Blob *other = Blob_new("bar", 4); + TEST_INT_EQ(runner, Blob_Get_Size(blob), Blob_Get_Size(other), + "same length"); + TEST_FALSE(runner, Blob_Equals(blob, (Obj*)other), + "Different content spoils Equals"); + DECREF(other); + } + + TEST_TRUE(runner, Blob_Equals_Bytes(blob, "foo", 4), "Equals_Bytes"); + TEST_FALSE(runner, Blob_Equals_Bytes(blob, "foo", 3), + "Equals_Bytes spoiled by different size"); + TEST_FALSE(runner, Blob_Equals_Bytes(blob, "bar", 4), + "Equals_Bytes spoiled by different content"); + + DECREF(blob); +} + +static void +test_Clone(TestBatchRunner *runner) { + Blob *blob = Blob_new("foo", 3); + Blob *twin = Blob_Clone(blob); + TEST_TRUE(runner, Blob_Equals(blob, (Obj*)twin), "Clone"); + DECREF(blob); + DECREF(twin); +} + +static void +test_compare(TestBatchRunner *runner) { + { + Blob *a = Blob_new("foo", 4); + Blob *b = Blob_new("foo", 4); + TEST_INT_EQ(runner, Blob_compare(&a, &b), 0, + "Blob_compare returns 0 for equal Blobs"); + DECREF(a); + DECREF(b); + } + + { + Blob *a = Blob_new("foo", 3); + Blob *b = Blob_new("foo\0b", 5); + TEST_TRUE(runner, Blob_compare(&a, &b) < 0, "shorter Blob sorts first"); + DECREF(a); + DECREF(b); + } + + { + Blob *a = Blob_new("foo\0a", 5); + Blob *b = Blob_new("foo\0b", 5); + TEST_TRUE(runner, Blob_compare(&a, &b) < 0, + "NULL doesn't interfere with Blob_compare"); + DECREF(a); + DECREF(b); + } +} + +void +TestBlob_Run_IMP(TestBlob *self, TestBatchRunner *runner) { + TestBatchRunner_Plan(runner, (TestBatch*)self, 11); + test_Equals(runner); + test_Clone(runner); + test_compare(runner); +} + + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1b1789a2/runtime/core/Clownfish/Test/TestBlob.cfh ---------------------------------------------------------------------- diff --git a/runtime/core/Clownfish/Test/TestBlob.cfh b/runtime/core/Clownfish/Test/TestBlob.cfh new file mode 100644 index 0000000..4d3d4b6 --- /dev/null +++ b/runtime/core/Clownfish/Test/TestBlob.cfh @@ -0,0 +1,28 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +parcel TestClownfish; + +class Clownfish::Test::TestBlob inherits Clownfish::TestHarness::TestBatch { + + inert incremented TestBlob* + new(); + + void + Run(TestBlob *self, TestBatchRunner *runner); +} + + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/1b1789a2/runtime/perl/t/core/021-blob.t ---------------------------------------------------------------------- diff --git a/runtime/perl/t/core/021-blob.t b/runtime/perl/t/core/021-blob.t new file mode 100644 index 0000000..1e280a1 --- /dev/null +++ b/runtime/perl/t/core/021-blob.t @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +use strict; +use warnings; + +use Clownfish::Test; +my $success = Clownfish::Test::run_tests("Clownfish::Test::TestBlob"); + +exit($success ? 0 : 1); +
