Merge pull request #60 from realm/al-os

First pass at object_store refactor
This commit is contained in:
Ari Lazier 2015-10-13 17:16:27 -07:00
commit 4cf19d0e87
12 changed files with 290 additions and 200 deletions

View File

@ -21,8 +21,8 @@
02601F121BA10228007C91FF /* transact_log_handler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 02601F101BA10228007C91FF /* transact_log_handler.hpp */; };
0270BC4C1B7CFC0D00010E03 /* RealmJS.h in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC3E1B7CFC0D00010E03 /* RealmJS.h */; settings = {ATTRIBUTES = (Public, ); }; };
0270BC4D1B7CFC0D00010E03 /* RealmJS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC3F1B7CFC0D00010E03 /* RealmJS.mm */; };
0270BC4E1B7CFC0D00010E03 /* RJSArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC401B7CFC0D00010E03 /* RJSArray.cpp */; };
0270BC4F1B7CFC0D00010E03 /* RJSArray.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC411B7CFC0D00010E03 /* RJSArray.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
0270BC4E1B7CFC0D00010E03 /* RJSList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC401B7CFC0D00010E03 /* RJSList.cpp */; };
0270BC4F1B7CFC0D00010E03 /* RJSList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC411B7CFC0D00010E03 /* RJSList.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
0270BC501B7CFC0D00010E03 /* RJSObject.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC421B7CFC0D00010E03 /* RJSObject.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
0270BC511B7CFC0D00010E03 /* RJSObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC431B7CFC0D00010E03 /* RJSObject.mm */; };
0270BC521B7CFC0D00010E03 /* RJSRealm.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC441B7CFC0D00010E03 /* RJSRealm.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
@ -33,7 +33,6 @@
0270BC571B7CFC0D00010E03 /* RJSSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC491B7CFC0D00010E03 /* RJSSchema.mm */; };
0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
0270BC591B7CFC0D00010E03 /* RJSUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC4B1B7CFC0D00010E03 /* RJSUtil.mm */; };
0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */; };
0270BC681B7CFC1C00010E03 /* object_accessor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */; };
0270BC691B7CFC1C00010E03 /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */; };
0270BC6A1B7CFC1C00010E03 /* object_schema.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */; };
@ -54,6 +53,8 @@
0270BCD11B7D067300010E03 /* RealmReactModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 0270BCD01B7D067300010E03 /* RealmReactModule.m */; };
02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; };
02B58CCE1AE99D4D009B348C /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; };
02C0864E1BCDB27000942F9C /* list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02C0864C1BCDB27000942F9C /* list.cpp */; settings = {ASSET_TAGS = (); }; };
02C0864F1BCDB27000942F9C /* list.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 02C0864D1BCDB27000942F9C /* list.hpp */; settings = {ASSET_TAGS = (); }; };
02D456DA1B7E59A500EE1299 /* ArrayTests.js in Resources */ = {isa = PBXBuildFile; fileRef = 02D456D91B7E59A500EE1299 /* ArrayTests.js */; };
02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; };
/* End PBXBuildFile section */
@ -143,8 +144,8 @@
02601F101BA10228007C91FF /* transact_log_handler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = transact_log_handler.hpp; path = "src/object-store/transact_log_handler.hpp"; sourceTree = "<group>"; };
0270BC3E1B7CFC0D00010E03 /* RealmJS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJS.h; path = src/RealmJS.h; sourceTree = "<group>"; };
0270BC3F1B7CFC0D00010E03 /* RealmJS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJS.mm; path = src/RealmJS.mm; sourceTree = "<group>"; };
0270BC401B7CFC0D00010E03 /* RJSArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RJSArray.cpp; path = src/RJSArray.cpp; sourceTree = "<group>"; };
0270BC411B7CFC0D00010E03 /* RJSArray.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSArray.hpp; path = src/RJSArray.hpp; sourceTree = "<group>"; };
0270BC401B7CFC0D00010E03 /* RJSList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RJSList.cpp; path = src/RJSList.cpp; sourceTree = "<group>"; };
0270BC411B7CFC0D00010E03 /* RJSList.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSList.hpp; path = src/RJSList.hpp; sourceTree = "<group>"; };
0270BC421B7CFC0D00010E03 /* RJSObject.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSObject.hpp; path = src/RJSObject.hpp; sourceTree = "<group>"; };
0270BC431B7CFC0D00010E03 /* RJSObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RJSObject.mm; path = src/RJSObject.mm; sourceTree = "<group>"; };
0270BC441B7CFC0D00010E03 /* RJSRealm.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSRealm.hpp; path = src/RJSRealm.hpp; sourceTree = "<group>"; };
@ -156,7 +157,6 @@
0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSUtil.hpp; path = src/RJSUtil.hpp; sourceTree = "<group>"; };
0270BC4B1B7CFC0D00010E03 /* RJSUtil.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RJSUtil.mm; path = src/RJSUtil.mm; sourceTree = "<group>"; };
0270BC5A1B7CFC1300010E03 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = src/Info.plist; sourceTree = "<group>"; };
0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_accessor.cpp; path = "src/object-store/object_accessor.cpp"; sourceTree = "<group>"; };
0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = object_accessor.hpp; path = "src/object-store/object_accessor.hpp"; sourceTree = "<group>"; };
0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_schema.cpp; path = "src/object-store/object_schema.cpp"; sourceTree = "<group>"; };
0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = object_schema.hpp; path = "src/object-store/object_schema.hpp"; sourceTree = "<group>"; };
@ -183,6 +183,8 @@
02B58CB11AE99CEC009B348C /* RealmJS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RealmJS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
02B58CBC1AE99CEC009B348C /* RealmJSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmJSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
02C0864C1BCDB27000942F9C /* list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = list.cpp; path = "src/object-store/list.cpp"; sourceTree = "<group>"; };
02C0864D1BCDB27000942F9C /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = list.hpp; path = "src/object-store/list.hpp"; sourceTree = "<group>"; };
02D456D91B7E59A500EE1299 /* ArrayTests.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = ArrayTests.js; path = tests/ArrayTests.js; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
@ -219,7 +221,6 @@
0270BC3D1B7CFBFD00010E03 /* RealmJS */ = {
isa = PBXGroup;
children = (
0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */,
0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */,
0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */,
0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */,
@ -234,6 +235,8 @@
02601F021BA0F0C4007C91FF /* external_commit_helper.hpp */,
02601F051BA0F0CD007C91FF /* index_set.cpp */,
02601F061BA0F0CD007C91FF /* index_set.hpp */,
02C0864C1BCDB27000942F9C /* list.cpp */,
02C0864D1BCDB27000942F9C /* list.hpp */,
02601F0B1BA0F3A7007C91FF /* schema.cpp */,
02601F0C1BA0F3A7007C91FF /* schema.hpp */,
02601F0F1BA10228007C91FF /* transact_log_handler.cpp */,
@ -243,8 +246,8 @@
0270BC3F1B7CFC0D00010E03 /* RealmJS.mm */,
02258FB11BC6E2D00075F13A /* RealmRPC.h */,
02258FB21BC6E2D00075F13A /* RealmRPC.mm */,
0270BC401B7CFC0D00010E03 /* RJSArray.cpp */,
0270BC411B7CFC0D00010E03 /* RJSArray.hpp */,
0270BC401B7CFC0D00010E03 /* RJSList.cpp */,
0270BC411B7CFC0D00010E03 /* RJSList.hpp */,
0270BC421B7CFC0D00010E03 /* RJSObject.hpp */,
0270BC431B7CFC0D00010E03 /* RJSObject.mm */,
0270BC441B7CFC0D00010E03 /* RJSRealm.hpp */,
@ -337,7 +340,7 @@
files = (
0270BC4C1B7CFC0D00010E03 /* RealmJS.h in Headers */,
02258FB31BC6E2D00075F13A /* RealmRPC.h in Headers */,
0270BC4F1B7CFC0D00010E03 /* RJSArray.hpp in Headers */,
0270BC4F1B7CFC0D00010E03 /* RJSList.hpp in Headers */,
0270BC541B7CFC0D00010E03 /* RJSResults.hpp in Headers */,
0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */,
0270BC561B7CFC0D00010E03 /* RJSSchema.hpp in Headers */,
@ -353,6 +356,7 @@
02601F041BA0F0C4007C91FF /* external_commit_helper.hpp in Headers */,
02601F091BA0F0CD007C91FF /* index_set.hpp in Headers */,
0270BC6D1B7CFC1C00010E03 /* property.hpp in Headers */,
02C0864F1BCDB27000942F9C /* list.hpp in Headers */,
0270BC6F1B7CFC1C00010E03 /* results.hpp in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -563,11 +567,11 @@
02601F111BA10228007C91FF /* transact_log_handler.cpp in Sources */,
0270BC591B7CFC0D00010E03 /* RJSUtil.mm in Sources */,
0270BC551B7CFC0D00010E03 /* RJSResults.mm in Sources */,
02C0864E1BCDB27000942F9C /* list.cpp in Sources */,
02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */,
0270BC6B1B7CFC1C00010E03 /* object_store.cpp in Sources */,
0270BC701B7CFC1C00010E03 /* shared_realm.cpp in Sources */,
0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */,
0270BC4E1B7CFC0D00010E03 /* RJSArray.cpp in Sources */,
0270BC4E1B7CFC0D00010E03 /* RJSList.cpp in Sources */,
0270BC531B7CFC0D00010E03 /* RJSRealm.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -16,7 +16,7 @@
//
////////////////////////////////////////////////////////////////////////////
#include "RJSArray.hpp"
#include "RJSList.hpp"
#include "RJSObject.hpp"
#include "RJSUtil.hpp"
#include "object_accessor.hpp"
@ -24,60 +24,32 @@
using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
using namespace realm;
size_t ObjectArray::size() {
return link_view->size();
static inline List * RJSVerifiedList(JSObjectRef object) {
List *list = RJSGetInternal<List *>(object);
list->verify_attached();
return list;
}
Row ObjectArray::get(std::size_t row_ndx) {
verify_valid_row(row_ndx);
return link_view->get(row_ndx);
}
void ObjectArray::set(std::size_t row_ndx, std::size_t target_row_ndx) {
verify_valid_row(row_ndx);
link_view->set(row_ndx, target_row_ndx);
}
void ObjectArray::verify_valid_row(std::size_t row_ndx) {
size_t size = link_view->size();
if (row_ndx >= size) {
throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + ".");
}
}
void ObjectArray::verify_attached() {
if (!link_view->is_attached()) {
throw std::runtime_error("Tableview is not attached");
}
link_view->sync_if_needed();
}
static inline ObjectArray * RJSVerifiedArray(JSObjectRef object) {
ObjectArray *array = RJSGetInternal<ObjectArray *>(object);
array->verify_attached();
return array;
}
static inline ObjectArray * RJSVerifiedMutableArray(JSObjectRef object) {
ObjectArray *array = RJSVerifiedArray(object);
if (!array->realm->is_in_transaction()) {
static inline List * RJSVerifiedMutableList(JSObjectRef object) {
List *list = RJSVerifiedList(object);
if (!list->realm->is_in_transaction()) {
throw std::runtime_error("Can only mutate lists within a transaction.");
}
return array;
return list;
}
JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
try {
// index subscripting
ObjectArray *array = RJSVerifiedArray(object);
size_t size = array->size();
List *list = RJSVerifiedList(object);
size_t size = list->size();
std::string indexStr = RJSStringForJSString(propertyName);
if (indexStr == "length") {
return JSValueMakeNumber(ctx, size);
}
return RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(RJSValidatedPositiveIndex(indexStr))));
return RJSObjectCreate(ctx, Object(list->realm, list->object_schema, list->get(RJSValidatedPositiveIndex(indexStr))));
}
catch (std::out_of_range &exp) {
// getters for nonexistent properties in JS should always return undefined
@ -95,15 +67,15 @@ JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pr
}
}
bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) {
bool ListSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) {
try {
ObjectArray *array = RJSVerifiedMutableArray(object);
List *list = RJSVerifiedMutableList(object);
std::string indexStr = RJSStringForJSString(propertyName);
if (indexStr == "length") {
throw std::runtime_error("The 'length' property is readonly.");
}
array->set(RJSValidatedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(value), array->object_schema.name, false));
list->set(RJSValidatedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, list->realm, const_cast<JSValueRef &>(value), list->object_schema.name, false));
return true;
}
catch (std::invalid_argument &exp) {
@ -118,9 +90,9 @@ bool ArraySetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef property
}
}
void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) {
ObjectArray *array = RJSVerifiedArray(object);
size_t size = array->size();
void ListPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) {
List *list = RJSVerifiedList(object);
size_t size = list->size();
char str[32];
for (size_t i = 0; i < size; i++) {
@ -131,9 +103,9 @@ void ArrayPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccu
}
}
JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
JSValueRef ListPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
try {
ObjectArray *array = RJSVerifiedMutableArray(thisObject);
List *array = RJSVerifiedMutableList(thisObject);
RJSValidateArgumentCountIsAtLeast(argumentCount, 1);
for (size_t i = 0; i < argumentCount; i++) {
array->link_view->add(RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[i]), array->object_schema.name, false));
@ -148,18 +120,18 @@ JSValueRef ArrayPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj
return NULL;
}
JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
JSValueRef ListPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
try {
ObjectArray *array = RJSVerifiedMutableArray(thisObject);
List *list = RJSVerifiedMutableList(thisObject);
RJSValidateArgumentCount(argumentCount, 0);
size_t size = array->size();
size_t size = list->size();
if (size == 0) {
return JSValueMakeUndefined(ctx);
}
size_t index = size - 1;
JSValueRef obj = RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(index)));
array->link_view->remove(index);
JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm, list->object_schema, list->get(index)));
list->link_view->remove(index);
return obj;
}
catch (std::exception &exp) {
@ -170,9 +142,9 @@ JSValueRef ArrayPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObje
return NULL;
}
JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
JSValueRef ListUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
try {
ObjectArray *array = RJSVerifiedMutableArray(thisObject);
List *array = RJSVerifiedMutableList(thisObject);
RJSValidateArgumentCountIsAtLeast(argumentCount, 1);
for (size_t i = 0; i < argumentCount; i++) {
array->link_view->insert(i, RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[i]), array->object_schema.name, false));
@ -187,15 +159,15 @@ JSValueRef ArrayUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef this
return NULL;
}
JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
JSValueRef ListShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
try {
ObjectArray *array = RJSVerifiedMutableArray(thisObject);
List *list = RJSVerifiedMutableList(thisObject);
RJSValidateArgumentCount(argumentCount, 0);
if (array->size() == 0) {
if (list->size() == 0) {
return JSValueMakeUndefined(ctx);
}
JSValueRef obj = RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(0)));
array->link_view->remove(0);
JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm, list->object_schema, list->get(0)));
list->link_view->remove(0);
return obj;
}
catch (std::exception &exp) {
@ -206,10 +178,10 @@ JSValueRef ArrayShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb
return NULL;
}
JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
JSValueRef ListSplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) {
try {
ObjectArray *array = RJSVerifiedMutableArray(thisObject);
size_t size = array->size();
List *list = RJSVerifiedMutableList(thisObject);
size_t size = list->size();
RJSValidateArgumentCountIsAtLeast(argumentCount, 2);
long index = std::min<long>(RJSValidatedValueToNumber(ctx, arguments[0]), size);
@ -222,11 +194,11 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO
std::vector<JSObjectRef> removedObjects(remove);
for (size_t i = 0; i < remove; i++) {
removedObjects[i] = RJSObjectCreate(ctx, Object(array->realm, array->object_schema, array->get(index)));
array->link_view->remove(index);
removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm, list->object_schema, list->get(index)));
list->link_view->remove(index);
}
for (size_t i = 2; i < argumentCount; i++) {
array->link_view->insert(index + i - 2, RJSAccessor::to_object_index(ctx, array->realm, const_cast<JSValueRef &>(arguments[i]), array->object_schema.name, false));
list->link_view->insert(index + i - 2, RJSAccessor::to_object_index(ctx, list->realm, const_cast<JSValueRef &>(arguments[i]), list->object_schema.name, false));
}
return JSObjectMakeArray(ctx, remove, removedObjects.data(), jsException);
}
@ -238,20 +210,20 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO
return NULL;
}
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array) {
return RJSWrapObject<ObjectArray *>(ctx, RJSArrayClass(), array);
JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list) {
return RJSWrapObject<List *>(ctx, RJSListClass(), new List(list));
}
const JSStaticFunction RJSArrayFuncs[] = {
{"push", ArrayPush, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"pop", ArrayPop, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"shift", ArrayShift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"unshift", ArrayUnshift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"splice", ArraySplice, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
const JSStaticFunction RJSListFuncs[] = {
{"push", ListPush, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"pop", ListPop, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"shift", ListShift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"unshift", ListUnshift, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{"splice", ListSplice, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete},
{NULL, NULL},
};
JSClassRef RJSArrayClass() {
static JSClassRef s_arrayClass = RJSCreateWrapperClass<Object>("RealmArray", ArrayGetProperty, ArraySetProperty, RJSArrayFuncs, NULL, ArrayPropertyNames);
return s_arrayClass;
JSClassRef RJSListClass() {
static JSClassRef s_listClass = RJSCreateWrapperClass<Object>("RealmList", ListGetProperty, ListSetProperty, RJSListFuncs, NULL, ListPropertyNames);
return s_listClass;
}

View File

@ -16,4 +16,12 @@
//
////////////////////////////////////////////////////////////////////////////
#include "object_accessor.hpp"
#import "RJSUtil.hpp"
#import "shared_realm.hpp"
#import "list.hpp"
extern const JSStaticFunction RJSListFuncs[];
JSClassRef RJSListClass();
JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list);
JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException);

View File

@ -20,7 +20,7 @@
#import "RJSObject.hpp"
#import "RJSResults.hpp"
#import "RJSSchema.hpp"
#import "RJSArray.hpp"
#import "RJSList.hpp"
#import "object_store.hpp"
#import "object_accessor.hpp"
@ -29,49 +29,15 @@ using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
using namespace realm;
JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) {
Object *obj = RJSGetInternal<Object *>(jsObject);
std::string propName = RJSStringForJSString(jsPropertyName);
ObjectSchema &objectSchema = obj->object_schema;
Property *prop = objectSchema.property_for_name(propName);
if (!prop) {
try {
Object *obj = RJSGetInternal<Object *>(jsObject);
return obj->get_property_value<JSValueRef>(ctx, RJSStringForJSString(jsPropertyName));
} catch (std::exception &ex) {
if (exception) {
*exception = RJSMakeError(ctx, ex);
}
return NULL;
}
switch (prop->type) {
case PropertyTypeBool:
return JSValueMakeBoolean(ctx, obj->row.get_bool(prop->table_column));
case PropertyTypeInt:
return JSValueMakeNumber(ctx, obj->row.get_int(prop->table_column));
case PropertyTypeFloat:
return JSValueMakeNumber(ctx, obj->row.get_float(prop->table_column));
case PropertyTypeDouble:
return JSValueMakeNumber(ctx, obj->row.get_double(prop->table_column));
case PropertyTypeString:
return RJSValueForString(ctx, obj->row.get_string(prop->table_column));
case PropertyTypeData:
return RJSValueForString(ctx, (std::string)obj->row.get_binary(prop->table_column));
case PropertyTypeAny:
*exception = RJSMakeError(ctx, "'Any' type not supported");
return NULL;
case PropertyTypeDate: {
JSValueRef time = JSValueMakeNumber(ctx, obj->row.get_datetime(prop->table_column).get_datetime());
return JSObjectMakeDate(ctx, 1, &time, exception);
}
case PropertyTypeObject: {
auto linkObjectSchema = obj->realm->config().schema->find(prop->object_type);
TableRef table = ObjectStore::table_for_object_type(obj->realm->read_group(), linkObjectSchema->name);
if (obj->row.is_null_link(prop->table_column)) {
return JSValueMakeNull(ctx);
}
return RJSObjectCreate(ctx, Object(obj->realm, *linkObjectSchema, table->get(obj->row.get_link(prop->table_column))));
}
case PropertyTypeArray: {
auto arrayObjectSchema = obj->realm->config().schema->find(prop->object_type);
return RJSArrayCreate(ctx, new ObjectArray(obj->realm, *arrayObjectSchema, static_cast<LinkViewRef>(obj->row.get_linklist(prop->table_column))));
}
}
return NULL;
}
bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef value, JSValueRef* exception) {
@ -133,6 +99,9 @@ template<> JSValueRef RJSAccessor::default_value_for_property(JSContextRef ctx,
template<> bool RJSAccessor::is_null(JSContextRef ctx, JSValueRef &val) {
return JSValueIsUndefined(ctx, val) || JSValueIsNull(ctx, val);
}
template<> JSValueRef RJSAccessor::null_value(JSContextRef ctx) {
return JSValueMakeNull(ctx);
}
template<> bool RJSAccessor::to_bool(JSContextRef ctx, JSValueRef &val) {
if (!JSValueIsBoolean(ctx, val)) {
@ -140,22 +109,37 @@ template<> bool RJSAccessor::to_bool(JSContextRef ctx, JSValueRef &val) {
}
return JSValueToBoolean(ctx, val);
}
template<> JSValueRef RJSAccessor::from_bool(JSContextRef ctx, bool b) {
return JSValueMakeBoolean(ctx, b);
}
template<> long long RJSAccessor::to_long(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedValueToNumber(ctx, val);
}
template<> JSValueRef RJSAccessor::from_long(JSContextRef ctx, long long l) {
return JSValueMakeNumber(ctx, l);
}
template<> float RJSAccessor::to_float(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedValueToNumber(ctx, val);
}
template<> JSValueRef RJSAccessor::from_float(JSContextRef ctx, float f) {
return JSValueMakeNumber(ctx, f);
}
template<> double RJSAccessor::to_double(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedValueToNumber(ctx, val);
}
template<> JSValueRef RJSAccessor::from_double(JSContextRef ctx, double d) {
return JSValueMakeNumber(ctx, d);
}
template<> std::string RJSAccessor::to_string(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedStringForValue(ctx, val);
}
template<> JSValueRef RJSAccessor::from_string(JSContextRef ctx, StringData s) {
return RJSValueForString(ctx, s);
}
template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val) {
JSObjectRef object = RJSValidatedValueToObject(ctx, val, "Property must be a Date");
@ -176,6 +160,10 @@ template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val)
return DateTime(utc);
}
template<> JSValueRef RJSAccessor::from_datetime(JSContextRef ctx, DateTime dt) {
JSValueRef time = JSValueMakeNumber(ctx, dt.get_datetime());
return JSObjectMakeDate(ctx, 1, &time, NULL);
}
extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array);
@ -193,11 +181,16 @@ template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm &re
Object child = Object::create<JSValueRef>(ctx, realm, *object_schema, (JSValueRef)object, try_update);
return child.row.get_index();
}
template<> size_t RJSAccessor::array_size(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedArrayLength(ctx, RJSValidatedValueToObject(ctx, val));
template<> JSValueRef RJSAccessor::from_object(JSContextRef ctx, Object object) {
return RJSObjectCreate(ctx, object);
}
template<> JSValueRef RJSAccessor::array_value_at_index(JSContextRef ctx, JSValueRef &val, size_t index) {
template<> size_t RJSAccessor::list_size(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedListLength(ctx, RJSValidatedValueToObject(ctx, val));
}
template<> JSValueRef RJSAccessor::list_value_at_index(JSContextRef ctx, JSValueRef &val, size_t index) {
return RJSValidatedObjectAtIndex(ctx, RJSValidatedValueToObject(ctx, val), (unsigned int)index);
}
template<> JSValueRef RJSAccessor::from_list(JSContextRef ctx, List list) {
return RJSListCreate(ctx, list);
}

View File

@ -19,7 +19,7 @@
#import "RJSRealm.hpp"
#import "RJSObject.hpp"
#import "RJSResults.hpp"
#import "RJSArray.hpp"
#import "RJSList.hpp"
#import "RJSSchema.hpp"
#import "shared_realm.hpp"
@ -221,7 +221,7 @@ JSValueRef RealmObjects(JSContextRef ctx, JSObjectRef function, JSObjectRef this
JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array) {
// copy to dictionary
if (object_schema.properties.size() != RJSValidatedArrayLength(ctx, array)) {
if (object_schema.properties.size() != RJSValidatedListLength(ctx, array)) {
throw std::runtime_error("Array must contain values for all object properties");
}
@ -280,10 +280,10 @@ JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO
if (RJSIsValueArray(ctx, arguments[0]) ||
JSValueIsObjectOfClass(ctx, arguments[0], RJSResultsClass()) ||
JSValueIsObjectOfClass(ctx, arguments[0], RJSArrayClass()))
JSValueIsObjectOfClass(ctx, arguments[0], RJSListClass()))
{
JSObjectRef array = RJSValidatedValueToObject(ctx, arguments[0]);
size_t length = RJSValidatedArrayLength(ctx, array);
size_t length = RJSValidatedListLength(ctx, array);
for (long i = length-1; i >= 0; i--) {
JSValueRef object = RJSValidatedObjectAtIndex(ctx, array, (unsigned int)i);
RealmDelete(ctx, function, thisObject, 1, &object, jsException);

View File

@ -127,7 +127,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
size_t numProperties = RJSValidatedArrayLength(ctx, propertiesObject);
size_t numProperties = RJSValidatedListLength(ctx, propertiesObject);
for (unsigned int p = 0; p < numProperties; p++) {
JSObjectRef property = RJSValidatedObjectAtIndex(ctx, propertiesObject, p);
objectSchema.properties.emplace_back(RJSParseProperty(ctx, property));
@ -163,7 +163,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject) {
std::vector<ObjectSchema> schema;
size_t length = RJSValidatedArrayLength(ctx, jsonObject);
size_t length = RJSValidatedListLength(ctx, jsonObject);
for (unsigned int i = 0; i < length; i++) {
JSObjectRef jsonObjectSchema = RJSValidatedObjectAtIndex(ctx, jsonObject, i);
ObjectSchema objectSchema = RJSParseObjectSchema(ctx, jsonObjectSchema);

View File

@ -161,7 +161,7 @@ static inline std::string RJSValidatedStringProperty(JSContextRef ctx, JSObjectR
return RJSValidatedStringForValue(ctx, propertyValue);
}
static inline size_t RJSValidatedArrayLength(JSContextRef ctx, JSObjectRef object) {
static inline size_t RJSValidatedListLength(JSContextRef ctx, JSObjectRef object) {
JSValueRef exception = NULL;
static JSStringRef lengthString = JSStringCreateWithUTF8CString("length");
JSValueRef lengthValue = JSObjectGetProperty(ctx, object, lengthString, &exception);

View File

@ -24,7 +24,7 @@
#include "RealmJS.h"
#include "RJSObject.hpp"
#include "RJSResults.hpp"
#include "RJSArray.hpp"
#include "RJSList.hpp"
#include "RJSRealm.hpp"
#include "RJSUtil.hpp"
@ -140,7 +140,7 @@ using RPCRequest = std::function<NSDictionary *(NSDictionary *dictionary)>;
JSValueRef exception = NULL;
static JSStringRef lengthPropertyName = JSStringCreateWithUTF8CString("length");
JSValueRef lengthValue = ArrayGetProperty(_context, _objects[listId], lengthPropertyName, &exception);
JSValueRef lengthValue = ListGetProperty(_context, _objects[listId], lengthPropertyName, &exception);
size_t length = JSValueToNumber(_context, lengthValue, &exception);
if (exception) {
@ -154,7 +154,7 @@ using RPCRequest = std::function<NSDictionary *(NSDictionary *dictionary)>;
JSValueRef exception = NULL;
JSStringRef indexPropertyName = JSStringCreateWithUTF8CString(std::to_string(index).c_str());
JSValueRef objectValue = ArrayGetProperty(_context, _objects[listId], indexPropertyName, &exception);
JSValueRef objectValue = ListGetProperty(_context, _objects[listId], indexPropertyName, &exception);
JSStringRelease(indexPropertyName);
if (exception) {
@ -166,7 +166,7 @@ using RPCRequest = std::function<NSDictionary *(NSDictionary *dictionary)>;
_requests["/call_list_method"] = [=](NSDictionary *dict) {
NSString *name = dict[@"name"];
return [self performObjectMethod:name.UTF8String
classMethods:RJSArrayFuncs
classMethods:RJSListFuncs
args:dict[@"arguments"]
objectId:[dict[@"listId"] unsignedLongValue]];
};
@ -249,14 +249,14 @@ using RPCRequest = std::function<NSDictionary *(NSDictionary *dictionary)>;
@"schema": [self objectSchemaToJSONObject:object->object_schema]
};
}
else if (JSValueIsObjectOfClass(_context, value, RJSArrayClass())) {
realm::ObjectArray *array = RJSGetInternal<realm::ObjectArray *>(jsObject);
else if (JSValueIsObjectOfClass(_context, value, RJSListClass())) {
realm::List *list = RJSGetInternal<realm::List *>(jsObject);
RPCObjectID oid = [self storeObject:jsObject];
return @{
@"type": @(RJSTypeGet(realm::PropertyTypeArray).c_str()),
@"id": @(oid),
@"size": @(array->link_view->size()),
@"schema": [self objectSchemaToJSONObject:array->object_schema]
@"size": @(list->link_view->size()),
@"schema": [self objectSchemaToJSONObject:list->object_schema]
};
}
else if (JSValueIsObjectOfClass(_context, value, RJSResultsClass())) {
@ -270,7 +270,7 @@ using RPCRequest = std::function<NSDictionary *(NSDictionary *dictionary)>;
};
}
else if (RJSIsValueArray(_context, value)) {
size_t length = RJSValidatedArrayLength(_context, jsObject);
size_t length = RJSValidatedListLength(_context, jsObject);
NSMutableArray *array = [NSMutableArray new];
for (unsigned int i = 0; i < length; i++) {
[array addObject:[self resultForJSValue:JSObjectGetPropertyAtIndex(_context, jsObject, i, NULL)]];

50
src/object-store/list.cpp Normal file
View File

@ -0,0 +1,50 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed 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.
//
////////////////////////////////////////////////////////////////////////////
#include "list.hpp"
#import <stdexcept>
using namespace realm;
size_t List::size() {
return link_view->size();
}
Row List::get(std::size_t row_ndx) {
verify_valid_row(row_ndx);
return link_view->get(row_ndx);
}
void List::set(std::size_t row_ndx, std::size_t target_row_ndx) {
verify_valid_row(row_ndx);
link_view->set(row_ndx, target_row_ndx);
}
void List::verify_valid_row(std::size_t row_ndx) {
size_t size = link_view->size();
if (row_ndx >= size) {
throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + ".");
}
}
void List::verify_attached() {
if (!link_view->is_attached()) {
throw std::runtime_error("Tableview is not attached");
}
link_view->sync_if_needed();
}

View File

@ -16,13 +16,15 @@
//
////////////////////////////////////////////////////////////////////////////
#import "RJSUtil.hpp"
#ifndef REALM_LIST_HPP
#define REALM_LIST_HPP
#import "shared_realm.hpp"
#import <realm/link_view.hpp>
namespace realm {
struct ObjectArray {
ObjectArray(SharedRealm &r, ObjectSchema &s, LinkViewRef l) : realm(r), object_schema(s), link_view(l) {}
struct List {
List(SharedRealm &r, ObjectSchema &s, LinkViewRef l) : realm(r), object_schema(s), link_view(l) {}
// FIXME - all should be const
SharedRealm realm;
ObjectSchema &object_schema;
@ -36,8 +38,5 @@ namespace realm {
};
}
extern const JSStaticFunction RJSArrayFuncs[];
JSClassRef RJSArrayClass();
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::ObjectArray *array);
JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException);
#endif /* REALM_LIST_HPP */

View File

@ -21,43 +21,9 @@
#include <string>
#include "shared_realm.hpp"
#include "list.hpp"
namespace realm {
template<typename ValueType, typename ContextType>
class NativeAccessor {
public:
//
// Value converters - template specializations must be implemented for each platform
//
static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
static bool to_bool(ContextType ctx, ValueType &val);
static long long to_long(ContextType ctx, ValueType &val);
static float to_float(ContextType ctx, ValueType &val);
static double to_double(ContextType ctx, ValueType &val);
static std::string to_string(ContextType ctx, ValueType &val);
static DateTime to_datetime(ContextType ctx, ValueType &val);
static bool is_null(ContextType ctx, ValueType &val);
// convert value to persisted object
// for existing objects return the existing row index
// for new/updated objects return the row index
static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update);
// array value acessors
static size_t array_size(ContextType ctx, ValueType &val);
static ValueType array_value_at_index(ContextType ctx, ValueType &val, size_t index);
//
// Deprecated
//
static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); }
};
class Object {
public:
@ -67,10 +33,13 @@ namespace realm {
ObjectSchema &object_schema;
Row row;
// property setter
// property getter/setter
template<typename ValueType, typename ContextType>
inline void set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update);
template<typename ValueType, typename ContextType>
inline ValueType get_property_value(ContextType ctx, std::string prop_name);
// create an Object from a native representation
template<typename ValueType, typename ContextType>
static inline Object create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update);
@ -78,6 +47,53 @@ namespace realm {
private:
template<typename ValueType, typename ContextType>
inline void set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update);
template<typename ValueType, typename ContextType>
inline ValueType get_property_value_impl(ContextType ctx, Property &property);
};
//
// Value converters - template specializations must be implemented for each platform in order to call templated methods on Object
//
template<typename ValueType, typename ContextType>
class NativeAccessor {
public:
static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
static bool to_bool(ContextType, ValueType &);
static ValueType from_bool(ContextType, bool);
static long long to_long(ContextType, ValueType &);
static ValueType from_long(ContextType, long long);
static float to_float(ContextType, ValueType &);
static ValueType from_float(ContextType, float);
static double to_double(ContextType, ValueType &);
static ValueType from_double(ContextType, double);
static std::string to_string(ContextType, ValueType &);
static ValueType from_string(ContextType, StringData);
static DateTime to_datetime(ContextType, ValueType &);
static ValueType from_datetime(ContextType, DateTime);
static bool is_null(ContextType, ValueType &);
static ValueType null_value(ContextType);
// convert value to persisted object
// for existing objects return the existing row index
// for new/updated objects return the row index
static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update);
static ValueType from_object(ContextType ctx, Object);
// list value acessors
static size_t list_size(ContextType ctx, ValueType &val);
static ValueType list_value_at_index(ContextType ctx, ValueType &val, size_t index);
static ValueType from_list(ContextType ctx, List);
//
// Deprecated
//
static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); }
};
//
@ -93,6 +109,16 @@ namespace realm {
set_property_value_impl(ctx, *prop, value, try_update);
};
template <typename ValueType, typename ContextType>
inline ValueType Object::get_property_value(ContextType ctx, std::string prop_name)
{
Property *prop = object_schema.property_for_name(prop_name);
if (!prop) {
throw std::runtime_error("Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'.");
}
return get_property_value_impl<ValueType>(ctx, *prop);
};
template <typename ValueType, typename ContextType>
inline void Object::set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update)
{
@ -140,9 +166,9 @@ namespace realm {
case PropertyTypeArray: {
realm::LinkViewRef link_view = row.get_linklist(column);
link_view->clear();
size_t count = Accessor::array_size(ctx, value);
size_t count = Accessor::list_size(ctx, value);
for (size_t i = 0; i < count; i++) {
ValueType element = Accessor::array_value_at_index(ctx, value, i);
ValueType element = Accessor::list_value_at_index(ctx, value, i);
link_view->add(Accessor::to_object_index(ctx, realm, element, property.object_type, try_update));
}
break;
@ -150,6 +176,44 @@ namespace realm {
}
}
template <typename ValueType, typename ContextType>
inline ValueType Object::get_property_value_impl(ContextType ctx, Property &property)
{
using Accessor = NativeAccessor<ValueType, ContextType>;
size_t column = property.table_column;
switch (property.type) {
case PropertyTypeBool:
return Accessor::from_bool(ctx, row.get_bool(column));
case PropertyTypeInt:
return Accessor::from_long(ctx, row.get_int(column));
case PropertyTypeFloat:
return Accessor::from_float(ctx, row.get_float(column));
case PropertyTypeDouble:
return Accessor::from_double(ctx, row.get_double(column));
case PropertyTypeString:
return Accessor::from_string(ctx, row.get_string(column));
case PropertyTypeData:
return Accessor::from_string(ctx, (std::string)row.get_binary(column));
case PropertyTypeAny:
throw "Any not supported";
case PropertyTypeDate:
return Accessor::from_datetime(ctx, row.get_datetime(column));
case PropertyTypeObject: {
auto linkObjectSchema = realm->config().schema->find(property.object_type);
TableRef table = ObjectStore::table_for_object_type(realm->read_group(), linkObjectSchema->name);
if (row.is_null_link(property.table_column)) {
return Accessor::null_value(ctx);
}
return Accessor::from_object(ctx, std::move(Object(realm, *linkObjectSchema, table->get(row.get_link(column)))));
}
case PropertyTypeArray: {
auto arrayObjectSchema = realm->config().schema->find(property.object_type);
return Accessor::from_list(ctx, std::move(List(realm, *arrayObjectSchema, static_cast<LinkViewRef>(row.get_linklist(column)))));
}
}
}
template<typename ValueType, typename ContextType>
inline Object Object::create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update)
{

View File

@ -243,9 +243,9 @@ static JSClassRef s_globalClass;
}
@end
@interface RJSArrayTests : RealmJSTests
@interface RJSListTests : RealmJSTests
@end
@implementation RJSArrayTests
@implementation RJSListTests
+ (NSString *)jsSuiteName {
return @"ArrayTests";
}