1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/js_api/js_api_tree_set.h" 17 18#include "ecmascript/containers/containers_errors.h" 19#include "ecmascript/tagged_tree.h" 20 21namespace panda::ecmascript { 22using ContainerError = containers::ContainerError; 23using ErrorFlag = containers::ErrorFlag; 24void JSAPITreeSet::Add(JSThread *thread, const JSHandle<JSAPITreeSet> &set, const JSHandle<JSTaggedValue> &value) 25{ 26 if (!TaggedTreeSet::IsKey(value.GetTaggedValue())) { 27 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue()); 28 RETURN_IF_ABRUPT_COMPLETION(thread); 29 CString errorMsg = 30 "The type of \"value\" must be Key of JS. Received value is: " + ConvertToString(*result); 31 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str()); 32 THROW_NEW_ERROR_AND_RETURN(thread, error); 33 } 34 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject())); 35 36 JSTaggedValue newSet = TaggedTreeSet::Add(thread, setHandle, value); 37 RETURN_IF_ABRUPT_COMPLETION(thread); 38 set->SetTreeSet(thread, newSet); 39} 40 41int JSAPITreeSet::GetSize() const 42{ 43 return TaggedTreeSet::Cast(GetTreeSet().GetTaggedObject())->NumberOfElements(); 44} 45 46JSTaggedValue JSAPITreeSet::GetKey(int entry) const 47{ 48 ASSERT_PRINT(entry < GetSize(), "entry must less than capacity"); 49 JSTaggedValue key = TaggedTreeSet::Cast(GetTreeSet().GetTaggedObject())->GetKey(entry); 50 return key.IsHole() ? JSTaggedValue::Undefined() : key; 51} 52 53bool JSAPITreeSet::Delete(JSThread *thread, const JSHandle<JSAPITreeSet> &set, const JSHandle<JSTaggedValue> &key) 54{ 55 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject())); 56 57 int entry = TaggedTreeSet::FindEntry(thread, setHandle, key); 58 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); 59 if (entry < 0) { 60 return false; 61 } 62 JSTaggedValue newSet = TaggedTreeSet::Delete(thread, setHandle, entry); 63 set->SetTreeSet(thread, newSet); 64 return true; 65} 66 67bool JSAPITreeSet::Has(JSThread *thread, const JSHandle<JSAPITreeSet> &set, const JSHandle<JSTaggedValue> &key) 68{ 69 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject())); 70 return TaggedTreeSet::FindEntry(thread, setHandle, key) >= 0; 71} 72 73void JSAPITreeSet::Clear(const JSThread *thread, const JSHandle<JSAPITreeSet> &set) 74{ 75 int cap = set->GetSize(); 76 if (cap == 0) { 77 return; 78 } 79 JSTaggedValue fn = TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject())->GetCompare(); 80 JSHandle<JSTaggedValue> compareFn = JSHandle<JSTaggedValue>(thread, fn); 81 JSTaggedValue internal = TaggedTreeSet::Create(thread, cap); 82 if (!compareFn->IsUndefined() && !compareFn->IsNull()) { 83 TaggedTreeSet::Cast(internal.GetTaggedObject())->SetCompare(thread, compareFn.GetTaggedValue()); 84 } 85 set->SetTreeSet(thread, internal); 86} 87 88JSTaggedValue JSAPITreeSet::PopFirst(JSThread *thread, const JSHandle<JSAPITreeSet> &set) 89{ 90 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject())); 91 int entry = setHandle->GetMinimum(setHandle->GetRootEntries()); 92 if (entry < 0) { 93 return JSTaggedValue::Undefined(); 94 } 95 JSHandle<JSTaggedValue> value(thread, setHandle->GetKey(entry)); 96 JSTaggedValue newSet = TaggedTreeSet::Delete(thread, setHandle, entry); 97 set->SetTreeSet(thread, newSet); 98 return value.GetTaggedValue(); 99} 100 101JSTaggedValue JSAPITreeSet::PopLast(JSThread *thread, const JSHandle<JSAPITreeSet> &set) 102{ 103 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject())); 104 int entry = setHandle->GetMaximum(setHandle->GetRootEntries()); 105 if (entry < 0) { 106 return JSTaggedValue::Undefined(); 107 } 108 JSHandle<JSTaggedValue> value(thread, setHandle->GetKey(entry)); 109 JSTaggedValue newSet = TaggedTreeSet::Delete(thread, setHandle, entry); 110 set->SetTreeSet(thread, newSet); 111 return value.GetTaggedValue(); 112} 113} // namespace panda::ecmascript 114