You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2013/07/31 03:11:16 UTC
[lucy-commits] [4/6] git commit: refs/heads/move-dumpable - Add dump() and load() to
Freezer.
Add dump() and load() to Freezer.
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/6589307a
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/6589307a
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/6589307a
Branch: refs/heads/move-dumpable
Commit: 6589307a013eb4190a6a0345c92219af95e44fdb
Parents: 105a7e9
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Jul 24 17:38:34 2013 -0700
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Jul 30 17:57:23 2013 -0700
----------------------------------------------------------------------
core/Lucy/Test/Util/TestFreezer.c | 54 ++++++++---
core/Lucy/Util/Freezer.c | 168 +++++++++++++++++++++++++++++++++
core/Lucy/Util/Freezer.cfh | 15 +++
3 files changed, 226 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy/blob/6589307a/core/Lucy/Test/Util/TestFreezer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Test/Util/TestFreezer.c b/core/Lucy/Test/Util/TestFreezer.c
index fd8b172..ac45db7 100644
--- a/core/Lucy/Test/Util/TestFreezer.c
+++ b/core/Lucy/Test/Util/TestFreezer.c
@@ -52,6 +52,20 @@ S_freeze_thaw(Obj *object) {
}
}
+// Return the result of round-tripping the object through dump() and load().
+static Obj*
+S_dump_load(Obj *object) {
+ if (object) {
+ Obj *dump = Freezer_dump(object);
+ Obj *loaded = Freezer_load(dump);
+ DECREF(dump);
+ return loaded;
+ }
+ else {
+ return NULL;
+ }
+}
+
static void
test_bytebuf(TestBatchRunner *runner) {
ByteBuf *wanted = BB_new_bytes("foobar", 6);
@@ -75,7 +89,6 @@ test_charbuf(TestBatchRunner *runner) {
static void
test_hash(TestBatchRunner *runner) {
Hash *wanted = Hash_new(0);
- Hash *got;
for (uint32_t i = 0; i < 10; i++) {
CharBuf *cb = TestUtils_random_string(rand() % 1200);
@@ -84,11 +97,20 @@ test_hash(TestBatchRunner *runner) {
Hash_Store(wanted, (Obj*)num, (Obj*)cb);
}
- got = (Hash*)S_freeze_thaw((Obj*)wanted);
- TEST_TRUE(runner, got && Hash_Equals(wanted, (Obj*)got),
- "Round trip through serialization.");
+ {
+ Hash *got = (Hash*)S_freeze_thaw((Obj*)wanted);
+ TEST_TRUE(runner, got && Hash_Equals(wanted, (Obj*)got),
+ "Round trip through serialization.");
+ DECREF(got);
+ }
+
+ {
+ Obj *got = S_dump_load((Obj*)wanted);
+ TEST_TRUE(runner, Hash_Equals(wanted, got),
+ "Dump => Load round trip");
+ DECREF(got);
+ }
- DECREF(got);
DECREF(wanted);
}
@@ -128,19 +150,29 @@ test_num(TestBatchRunner *runner) {
static void
test_varray(TestBatchRunner *runner) {
VArray *array = VA_new(0);
- VArray *dupe;
VA_Store(array, 1, (Obj*)CB_newf("foo"));
VA_Store(array, 3, (Obj*)CB_newf("bar"));
- dupe = (VArray*)S_freeze_thaw((Obj*)array);
- TEST_TRUE(runner, dupe && VA_Equals(array, (Obj*)dupe),
- "Round trip through FREEZE/THAW");
- DECREF(dupe);
+
+ {
+ Obj *got = S_freeze_thaw((Obj*)array);
+ TEST_TRUE(runner, got && VA_Equals(array, got),
+ "Round trip through FREEZE/THAW");
+ DECREF(got);
+ }
+
+ {
+ Obj *got = S_dump_load((Obj*)array);
+ TEST_TRUE(runner, got && VA_Equals(array, got),
+ "Dump => Load round trip");
+ DECREF(got);
+ }
+
DECREF(array);
}
void
TestFreezer_run(TestFreezer *self, TestBatchRunner *runner) {
- TestBatchRunner_Plan(runner, (TestBatch*)self, 9);
+ TestBatchRunner_Plan(runner, (TestBatch*)self, 10);
test_bytebuf(runner);
test_charbuf(runner);
test_hash(runner);
http://git-wip-us.apache.org/repos/asf/lucy/blob/6589307a/core/Lucy/Util/Freezer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/Freezer.c b/core/Lucy/Util/Freezer.c
index fecd092..2f9bf63 100644
--- a/core/Lucy/Util/Freezer.c
+++ b/core/Lucy/Util/Freezer.c
@@ -20,10 +20,13 @@
#include "Lucy/Util/Freezer.h"
#include "Lucy/Store/InStream.h"
#include "Lucy/Store/OutStream.h"
+#include "Lucy/Analysis/Analyzer.h"
#include "Lucy/Document/Doc.h"
#include "Lucy/Index/Similarity.h"
#include "Lucy/Index/DocVector.h"
#include "Lucy/Index/TermVector.h"
+#include "Lucy/Plan/FieldType.h"
+#include "Lucy/Plan/Schema.h"
#include "Lucy/Search/Query.h"
#include "Lucy/Search/SortRule.h"
#include "Lucy/Search/SortSpec.h"
@@ -358,3 +361,168 @@ Freezer_read_hash(InStream *instream) {
return Freezer_deserialize_hash(hash, instream);
}
+static Obj*
+S_dump_array(VArray *array) {
+ VArray *dump = VA_new(VA_Get_Size(array));
+ for (uint32_t i = 0, max = VA_Get_Size(array); i < max; i++) {
+ Obj *elem = VA_Fetch(array, i);
+ if (elem) {
+ VA_Store(dump, i, Freezer_dump(elem));
+ }
+ }
+ return (Obj*)dump;
+}
+
+Obj*
+S_dump_hash(Hash *hash) {
+ Hash *dump = Hash_new(Hash_Get_Size(hash));
+ Obj *key;
+ Obj *value;
+
+ Hash_Iterate(hash);
+ while (Hash_Next(hash, &key, &value)) {
+ // Since JSON only supports text hash keys, dump() can only support
+ // text hash keys.
+ CERTIFY(key, CHARBUF);
+ Hash_Store(dump, key, Obj_Dump(value));
+ }
+
+ return (Obj*)dump;
+}
+
+Obj*
+Freezer_dump(Obj *obj) {
+ if (Obj_Is_A(obj, CHARBUF)) {
+ return (Obj*)Obj_To_String(obj);
+ }
+ else if (Obj_Is_A(obj, VARRAY)) {
+ return S_dump_array((VArray*)obj);
+ }
+ else if (Obj_Is_A(obj, HASH)) {
+ return S_dump_hash((Hash*)obj);
+ }
+ else if (Obj_Is_A(obj, ANALYZER)) {
+ return Analyzer_Dump((Analyzer*)obj);
+ }
+ else if (Obj_Is_A(obj, DOC)) {
+ return (Obj*)Doc_Dump((Doc*)obj);
+ }
+ else if (Obj_Is_A(obj, SIMILARITY)) {
+ return Sim_Dump((Similarity*)obj);
+ }
+ else if (Obj_Is_A(obj, FIELDTYPE)) {
+ return FType_Dump((FieldType*)obj);
+ }
+ else if (Obj_Is_A(obj, SCHEMA)) {
+ return (Obj*)Schema_Dump((Schema*)obj);
+ }
+ else if (Obj_Is_A(obj, QUERY)) {
+ return Query_Dump((Query*)obj);
+ }
+ else {
+ return (Obj*)Obj_To_String(obj);
+ }
+}
+
+static Obj*
+S_load_via_load_method(VTable *vtable, Obj *dump) {
+ Obj *dummy = VTable_Make_Obj(vtable);
+ Obj *loaded = NULL;
+ if (Obj_Is_A(dummy, ANALYZER)) {
+ loaded = Analyzer_Load((Analyzer*)dummy, dump);
+ }
+ else if (Obj_Is_A(dummy, DOC)) {
+ loaded = (Obj*)Doc_Load((Doc*)dummy, dump);
+ }
+ else if (Obj_Is_A(dummy, SIMILARITY)) {
+ loaded = (Obj*)Sim_Load((Similarity*)dummy, dump);
+ }
+ else if (Obj_Is_A(dummy, FIELDTYPE)) {
+ loaded = FType_Load((FieldType*)dummy, dump);
+ }
+ else if (Obj_Is_A(dummy, SCHEMA)) {
+ loaded = (Obj*)Schema_Load((Schema*)dummy, dump);
+ }
+ else if (Obj_Is_A(dummy, QUERY)) {
+ loaded = Query_Load((Query*)dummy, dump);
+ }
+ else {
+ DECREF(dummy);
+ THROW(ERR, "Don't know how to load '%o'", VTable_Get_Name(vtable));
+ }
+
+ DECREF(dummy);
+ return loaded;
+}
+
+static Obj*
+S_load_from_hash(Hash *dump) {
+ CharBuf *class_name = (CharBuf*)Hash_Fetch_Str(dump, "_class", 6);
+
+ // Assume that the presence of the "_class" key paired with a valid class
+ // name indicates the output of a dump() rather than an ordinary Hash.
+ if (class_name && CB_Is_A(class_name, CHARBUF)) {
+ VTable *vtable = VTable_fetch_vtable(class_name);
+
+ if (!vtable) {
+ CharBuf *parent_class = VTable_find_parent_class(class_name);
+ if (parent_class) {
+ VTable *parent = VTable_singleton(parent_class, NULL);
+ vtable = VTable_singleton(class_name, parent);
+ DECREF(parent_class);
+ }
+ else {
+ // TODO: Fix load() so that it works with ordinary hash keys
+ // named "_class".
+ THROW(ERR, "Can't find class '%o'", class_name);
+ }
+ }
+
+ // Dispatch to an alternate Load() method.
+ if (vtable) {
+ return S_load_via_load_method(vtable, (Obj*)dump);
+ }
+
+ }
+
+ // It's an ordinary Hash.
+ Hash *loaded = Hash_new(Hash_Get_Size(dump));
+ Obj *key;
+ Obj *value;
+ Hash_Iterate(dump);
+ while (Hash_Next(dump, &key, &value)) {
+ Hash_Store(loaded, key, Freezer_load(value));
+ }
+
+ return (Obj*)loaded;
+
+}
+
+
+Obj*
+S_load_from_array(VArray *dump) {
+ VArray *loaded = VA_new(VA_Get_Size(dump));
+
+ for (uint32_t i = 0, max = VA_Get_Size(dump); i < max; i++) {
+ Obj *elem_dump = VA_Fetch(dump, i);
+ if (elem_dump) {
+ VA_Store(loaded, i, Freezer_load(elem_dump));
+ }
+ }
+
+ return (Obj*)loaded;
+}
+
+Obj*
+Freezer_load(Obj *obj) {
+ if (Obj_Is_A(obj, HASH)) {
+ return S_load_from_hash((Hash*)obj);
+ }
+ else if (Obj_Is_A(obj, VARRAY)) {
+ return S_load_from_array((VArray*)obj);
+ }
+ else {
+ return Obj_Clone(obj);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/6589307a/core/Lucy/Util/Freezer.cfh
----------------------------------------------------------------------
diff --git a/core/Lucy/Util/Freezer.cfh b/core/Lucy/Util/Freezer.cfh
index d84ec88..93b152f 100644
--- a/core/Lucy/Util/Freezer.cfh
+++ b/core/Lucy/Util/Freezer.cfh
@@ -40,6 +40,21 @@ inert class Lucy::Util::Freezer {
inert incremented Obj*
deserialize(Obj *obj, InStream *instream);
+ /** Return a representation of the object using only scalars, hashes, and
+ * arrays. Some classes support JSON serialization via dump() and its
+ * companion, load(); for others, dump() is only a debugging aid.
+ * The default simply calls To_String().
+ */
+ inert incremented Obj*
+ dump(Obj *obj);
+
+ /** Create an object from the output of a call to dump().
+ *
+ * @param dump The output of dump().
+ */
+ inert incremented Obj*
+ load(Obj *dump);
+
inert void
serialize_charbuf(CharBuf *charbuf, OutStream *outstream);