diff --git a/src/RJSList.cpp b/src/RJSList.cpp index 06fa235e..7c597043 100644 --- a/src/RJSList.cpp +++ b/src/RJSList.cpp @@ -12,15 +12,6 @@ using namespace realm; static inline List * RJSVerifiedList(JSObjectRef object) { List *list = RJSGetInternal(object); - list->verify_attached(); - return list; -} - -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 list; } @@ -55,13 +46,13 @@ JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pro bool ListSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException) { try { - List *list = RJSVerifiedMutableList(object); + List *list = RJSVerifiedList(object); std::string indexStr = RJSStringForJSString(propertyName); if (indexStr == "length") { throw std::runtime_error("The 'length' property is readonly."); } - list->set(RJSValidatedPositiveIndex(indexStr), RJSAccessor::to_object_index(ctx, list->realm(), const_cast(value), list->object_schema.name, false)); + list->set(ctx, value, RJSValidatedPositiveIndex(indexStr)); return true; } catch (std::invalid_argument &exp) { @@ -91,12 +82,12 @@ void ListPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccum JSValueRef ListPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *array = RJSVerifiedMutableList(thisObject); + List *list = RJSVerifiedList(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(arguments[i]), array->object_schema.name, false)); + list->add(ctx, arguments[i]); } - return JSValueMakeNumber(ctx, array->link_view()->size()); + return JSValueMakeNumber(ctx, list->size()); } catch (std::exception &exp) { if (jsException) { @@ -108,16 +99,17 @@ JSValueRef ListPush(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObje JSValueRef ListPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *list = RJSVerifiedMutableList(thisObject); + List *list = RJSVerifiedList(thisObject); RJSValidateArgumentCount(argumentCount, 0); size_t size = list->size(); if (size == 0) { + list->verify_in_tranaction(); return JSValueMakeUndefined(ctx); } size_t index = size - 1; JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(index))); - list->link_view()->remove(index); + list->remove(index); return obj; } catch (std::exception &exp) { @@ -130,12 +122,12 @@ JSValueRef ListPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObjec JSValueRef ListUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *array = RJSVerifiedMutableList(thisObject); + List *array = RJSVerifiedList(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(arguments[i]), array->object_schema.name, false)); + array->insert(ctx, arguments[i], i); } - return JSValueMakeNumber(ctx, array->link_view()->size()); + return JSValueMakeNumber(ctx, array->size()); } catch (std::exception &exp) { if (jsException) { @@ -147,13 +139,14 @@ JSValueRef ListUnshift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO JSValueRef ListShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *list = RJSVerifiedMutableList(thisObject); + List *list = RJSVerifiedList(thisObject); RJSValidateArgumentCount(argumentCount, 0); if (list->size() == 0) { + list->verify_in_tranaction(); return JSValueMakeUndefined(ctx); } JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(0))); - list->link_view()->remove(0); + list->remove(0); return obj; } catch (std::exception &exp) { @@ -166,7 +159,7 @@ JSValueRef ListShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj JSValueRef ListSplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* jsException) { try { - List *list = RJSVerifiedMutableList(thisObject); + List *list = RJSVerifiedList(thisObject); size_t size = list->size(); RJSValidateArgumentCountIsAtLeast(argumentCount, 2); @@ -181,10 +174,10 @@ JSValueRef ListSplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb std::vector removedObjects(remove); for (size_t i = 0; i < remove; i++) { removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(index))); - list->link_view()->remove(index); + list->remove(index); } for (size_t i = 2; i < argumentCount; i++) { - list->link_view()->insert(index + i - 2, RJSAccessor::to_object_index(ctx, list->realm(), const_cast(arguments[i]), list->object_schema.name, false)); + list->insert(ctx, arguments[i], index + i - 2); } return JSObjectMakeArray(ctx, remove, removedObjects.data(), jsException); } diff --git a/src/RJSSchema.mm b/src/RJSSchema.mm index 1c748c3a..165cb69e 100644 --- a/src/RJSSchema.mm +++ b/src/RJSSchema.mm @@ -50,35 +50,35 @@ static inline Property RJSParseProperty(JSContextRef ctx, JSObjectRef propertyOb } std::string type = RJSValidatedStringProperty(ctx, propertyObject, typeString); - if (type == "PropTypesBOOL") { + if (type == "bool") { prop.type = PropertyTypeBool; } - else if (type == "PropTypesINT") { + else if (type == "int") { prop.type = PropertyTypeInt; } - else if (type == "PropTypesFLOAT") { + else if (type == "float") { prop.type = PropertyTypeFloat; } - else if (type == "PropTypesDOUBLE") { + else if (type == "double") { prop.type = PropertyTypeDouble; } - else if (type == "PropTypesSTRING") { + else if (type == "string") { prop.type = PropertyTypeString; } - else if (type == "PropTypesDATE") { + else if (type == "date") { prop.type = PropertyTypeDate; } - else if (type == "PropTypesDATA") { + else if (type == "data") { prop.type = PropertyTypeData; } - else if (type == "PropTypesLIST") { + else if (type == "list") { prop.type = PropertyTypeArray; prop.object_type = RJSValidatedStringProperty(ctx, propertyObject, objectTypeString); } else { prop.type = PropertyTypeObject; prop.is_nullable = true; - prop.object_type = type == "PropTypesOBJECT" ? RJSValidatedStringProperty(ctx, propertyObject, objectTypeString) : type; + prop.object_type = type == "object" ? RJSValidatedStringProperty(ctx, propertyObject, objectTypeString) : type; } return prop; } diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index 1aa0b0c5..6967f80a 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -42,7 +42,6 @@ JSClassRef RJSCreateWrapperClass(const char * name, JSObjectGetPropertyCallback } std::string RJSTypeGet(realm::PropertyType propertyType); -std::string RJSTypeGet(std::string typeString); std::string RJSStringForJSString(JSStringRef jsString); std::string RJSStringForValue(JSContextRef ctx, JSValueRef value); diff --git a/src/RJSUtil.mm b/src/RJSUtil.mm index 66fd6035..20993469 100644 --- a/src/RJSUtil.mm +++ b/src/RJSUtil.mm @@ -25,23 +25,19 @@ JSValueRef RJSMakeError(JSContextRef ctx, const std::string &message) { std::string RJSTypeGet(PropertyType propertyType) { switch (propertyType) { - case PropertyTypeBool: return RJSTypeGet("BOOL"); - case PropertyTypeInt: return RJSTypeGet("INT"); - case PropertyTypeFloat: return RJSTypeGet("FLOAT"); - case PropertyTypeDouble:return RJSTypeGet("DOUBLE"); - case PropertyTypeString:return RJSTypeGet("STRING"); - case PropertyTypeDate: return RJSTypeGet("DATE"); - case PropertyTypeData: return RJSTypeGet("DATA"); - case PropertyTypeObject:return RJSTypeGet("OBJECT"); - case PropertyTypeArray: return RJSTypeGet("LIST"); + case PropertyTypeBool: return "bool"; + case PropertyTypeInt: return "int"; + case PropertyTypeFloat: return "float"; + case PropertyTypeDouble:return "double"; + case PropertyTypeString:return "string"; + case PropertyTypeDate: return "date"; + case PropertyTypeData: return "data"; + case PropertyTypeObject:return "object"; + case PropertyTypeArray: return "list"; default: return nullptr; } } -std::string RJSTypeGet(std::string propertyTypeString) { - return "PropTypes" + propertyTypeString; -} - std::string RJSStringForJSString(JSStringRef jsString) { std::string str; size_t maxSize = JSStringGetMaximumUTF8CStringSize(jsString); diff --git a/src/RealmJS.mm b/src/RealmJS.mm index df166946..aced242c 100644 --- a/src/RealmJS.mm +++ b/src/RealmJS.mm @@ -9,9 +9,12 @@ #import "RJSSchema.hpp" #include "shared_realm.hpp" +#include JSValueRef RJSTypeGet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { - return RJSValueForString(ctx, RJSTypeGet(RJSStringForJSString(propertyName))); + std::string str = RJSStringForJSString(propertyName); + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + return RJSValueForString(ctx, str); } JSClassRef RJSRealmTypeClass() { diff --git a/src/RealmRPC.cpp b/src/RealmRPC.cpp index 318714a0..bcc2ada0 100644 --- a/src/RealmRPC.cpp +++ b/src/RealmRPC.cpp @@ -228,7 +228,7 @@ json RPCServer::serialize_json_value(JSValueRef value) { return { {"type", RJSTypeGet(realm::PropertyTypeArray)}, {"id", store_object(js_object)}, - {"size", list->link_view()->size()}, + {"size", list->size()}, {"schema", serialize_object_schema(list->object_schema)} }; } diff --git a/src/object-store/list.cpp b/src/object-store/list.cpp index ff57ef27..1cbf1477 100644 --- a/src/object-store/list.cpp +++ b/src/object-store/list.cpp @@ -1,6 +1,20 @@ -/* Copyright 2015 Realm Inc - All Rights Reserved - * Proprietary and Confidential - */ +//////////////////////////////////////////////////////////////////////////// +// +// 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 @@ -8,22 +22,46 @@ using namespace realm; size_t List::size() { + verify_attached(); return m_link_view->size(); } Row List::get(std::size_t row_ndx) { + verify_attached(); verify_valid_row(row_ndx); return m_link_view->get(row_ndx); } void List::set(std::size_t row_ndx, std::size_t target_row_ndx) { + verify_attached(); + verify_in_tranaction(); verify_valid_row(row_ndx); m_link_view->set(row_ndx, target_row_ndx); } -void List::verify_valid_row(std::size_t row_ndx) { +void List::add(std::size_t target_row_ndx) { + verify_attached(); + verify_in_tranaction(); + m_link_view->add(target_row_ndx); +} + +void List::insert(std::size_t row_ndx, std::size_t target_row_ndx) { + verify_attached(); + verify_in_tranaction(); + verify_valid_row(row_ndx, true); + m_link_view->insert(row_ndx, target_row_ndx); +} + +void List::remove(std::size_t row_ndx) { + verify_attached(); + verify_in_tranaction(); + verify_valid_row(row_ndx); + m_link_view->remove(row_ndx); +} + +void List::verify_valid_row(std::size_t row_ndx, bool insertion) { size_t size = m_link_view->size(); - if (row_ndx >= size) { + if (row_ndx > size || (!insertion && 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) + "."); } } @@ -34,3 +72,9 @@ void List::verify_attached() { } m_link_view->sync_if_needed(); } + +void List::verify_in_tranaction() { + if (!m_realm->is_in_transaction()) { + throw std::runtime_error("Can only mutate a list within a transaction."); + } +} diff --git a/src/object-store/list.hpp b/src/object-store/list.hpp index 18ef44e7..54bbed41 100644 --- a/src/object-store/list.hpp +++ b/src/object-store/list.hpp @@ -1,6 +1,20 @@ -/* Copyright 2015 Realm Inc - All Rights Reserved - * Proprietary and Confidential - */ +//////////////////////////////////////////////////////////////////////////// +// +// 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. +// +//////////////////////////////////////////////////////////////////////////// #ifndef REALM_LIST_HPP #define REALM_LIST_HPP @@ -15,14 +29,27 @@ namespace realm { const ObjectSchema &object_schema; SharedRealm realm() { return m_realm; } - LinkViewRef link_view() { return m_link_view; } size_t size(); Row get(std::size_t row_ndx); void set(std::size_t row_ndx, std::size_t target_row_ndx); - void verify_valid_row(std::size_t row_ndx); + void add(size_t target_row_ndx); + void remove(size_t list_ndx); + void insert(size_t list_ndx, size_t target_row_ndx); + + template + void add(ContextType ctx, ValueType value); + + template + void insert(ContextType ctx, ValueType value, size_t list_ndx); + + template + void set(ContextType ctx, ValueType value, size_t list_ndx); + + void verify_valid_row(std::size_t row_ndx, bool insertion = false); void verify_attached(); + void verify_in_tranaction(); private: SharedRealm m_realm; @@ -31,4 +58,5 @@ namespace realm { } + #endif /* REALM_LIST_HPP */ diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index d1e78b80..5cc7a358 100644 --- a/src/object-store/object_accessor.hpp +++ b/src/object-store/object_accessor.hpp @@ -297,6 +297,27 @@ namespace realm { } return object; } + + // + // List implementation + // + template + void List::add(ContextType ctx, ValueType value) + { + add(NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + } + + template + void List::insert(ContextType ctx, ValueType value, size_t list_ndx) + { + insert(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + } + + template + void List::set(ContextType ctx, ValueType value, size_t list_ndx) + { + set(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + } } #endif /* defined(REALM_OBJECT_ACCESSOR_HPP) */ diff --git a/src/object-store/shared_realm.cpp b/src/object-store/shared_realm.cpp index d95b8bd2..9c0a4e1e 100644 --- a/src/object-store/shared_realm.cpp +++ b/src/object-store/shared_realm.cpp @@ -382,10 +382,6 @@ void Realm::close() m_notifier->remove_realm(this); } - if (m_group) { - m_shared_group->end_read(); - } - m_group = nullptr; m_shared_group = nullptr; m_history = nullptr; diff --git a/src/object-store/shared_realm.hpp b/src/object-store/shared_realm.hpp index 09685128..81b14bf7 100644 --- a/src/object-store/shared_realm.hpp +++ b/src/object-store/shared_realm.hpp @@ -197,12 +197,6 @@ namespace realm { public: UnitializedRealmException(std::string message) : std::runtime_error(message) {} }; - - class ClosedRealmException : public std::runtime_error - { - public: - ClosedRealmException(std::string message) : std::runtime_error(message) {} - }; } #endif /* defined(REALM_REALM_HPP) */