//////////////////////////////////////////////////////////////////////////// // // Copyright 2016 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. // //////////////////////////////////////////////////////////////////////////// #pragma once #include "js_collection.hpp" #include "js_object.hpp" #include "js_results.hpp" #include "js_types.hpp" #include "js_util.hpp" #include "shared_realm.hpp" #include "list.hpp" #include "parser.hpp" #include "query_builder.hpp" namespace realm { namespace js { template class List { using TContext = typename T::Context; using TObject = typename T::Object; using TValue = typename T::Value; using Object = Object; using Value = Value; using ReturnValue = ReturnValue; public: static TObject create_instance(TContext, realm::List &); // properties static void get_length(TContext, TObject, ReturnValue &); static void get_index(TContext, TObject, uint32_t, ReturnValue &); static bool set_index(TContext, TObject, uint32_t, TValue); // methods static void push(TContext, TObject, size_t, const TValue[], ReturnValue &); static void pop(TContext, TObject, size_t, const TValue[], ReturnValue &); static void unshift(TContext, TObject, size_t, const TValue[], ReturnValue &); static void shift(TContext, TObject, size_t, const TValue[], ReturnValue &); static void splice(TContext, TObject, size_t, const TValue[], ReturnValue &); static void snapshot(TContext, TObject, size_t, const TValue[], ReturnValue &); static void filtered(TContext, TObject, size_t, const TValue[], ReturnValue &); static void sorted(TContext, TObject, size_t, const TValue[], ReturnValue &); }; template struct ListClass : ClassDefinition> { using List = List; std::string const name = "List"; MethodMap const methods = { {"push", wrap}, {"pop", wrap}, {"unshift", wrap}, {"shift", wrap}, {"splice", wrap}, {"snapshot", wrap}, {"filtered", wrap}, {"sorted", wrap}, }; PropertyMap const properties = { {"length", {wrap, nullptr}}, }; IndexPropertyType const index_accessor = {wrap, wrap}; }; template typename T::Object List::create_instance(TContext ctx, realm::List &list) { return create_object>(ctx, new realm::List(list)); } template void List::get_length(TContext ctx, TObject object, ReturnValue &return_value) { auto list = get_internal>(object); return_value.set((uint32_t)list->size()); } template void List::get_index(TContext ctx, TObject object, uint32_t index, ReturnValue &return_value) { auto list = get_internal>(object); auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); return_value.set(RealmObject::create_instance(ctx, realm_object)); } template bool List::set_index(TContext ctx, TObject object, uint32_t index, TValue value) { auto list = get_internal>(object); list->set(ctx, value, index); return true; } template void List::push(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { validate_argument_count_at_least(argc, 1); auto list = get_internal>(this_object); for (size_t i = 0; i < argc; i++) { list->add(ctx, arguments[i]); } return_value.set((uint32_t)list->size()); } template void List::pop(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { validate_argument_count(argc, 0); auto list = get_internal>(this_object); size_t size = list->size(); if (size == 0) { list->verify_in_transaction(); return_value.set_undefined(); } else { size_t index = size - 1; auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); return_value.set(RealmObject::create_instance(ctx, realm_object)); list->remove(index); } } template void List::unshift(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { validate_argument_count_at_least(argc, 1); auto list = get_internal>(this_object); for (size_t i = 0; i < argc; i++) { list->insert(ctx, arguments[i], i); } return_value.set((uint32_t)list->size()); } template void List::shift(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { validate_argument_count(argc, 0); auto list = get_internal>(this_object); if (list->size() == 0) { list->verify_in_transaction(); return_value.set_undefined(); } else { auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(0)); return_value.set(RealmObject::create_instance(ctx, realm_object)); list->remove(0); } } template void List::splice(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { validate_argument_count_at_least(argc, 1); auto list = get_internal>(this_object); size_t size = list->size(); long index = std::min(Value::to_number(ctx, arguments[0]), size); if (index < 0) { index = std::max(size + index, 0); } size_t remove; if (argc < 2) { remove = size - index; } else { remove = std::max(Value::to_number(ctx, arguments[1]), 0); remove = std::min(remove, size - index); } std::vector removed_objects; removed_objects.reserve(remove); for (size_t i = 0; i < remove; i++) { auto realm_object = realm::Object(list->get_realm(), list->get_object_schema(), list->get(index)); removed_objects.push_back(RealmObject::create_instance(ctx, realm_object)); list->remove(index); } for (size_t i = 2; i < argc; i++) { list->insert(ctx, arguments[i], index + i - 2); } return_value.set(Object::create_array(ctx, removed_objects)); } template void List::snapshot(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { validate_argument_count(argc, 0); auto list = get_internal>(this_object); return_value.set(Results::create_instance(ctx, *list, false)); } template void List::filtered(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { validate_argument_count_at_least(argc, 1); auto list = get_internal>(this_object); return_value.set(Results::create_filtered(ctx, *list, argc, arguments)); } template void List::sorted(TContext ctx, TObject this_object, size_t argc, const TValue arguments[], ReturnValue &return_value) { validate_argument_count(argc, 1, 2); auto list = get_internal>(this_object); return_value.set(Results::create_sorted(ctx, *list, argc, arguments)); } } // js } // realm