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/js_tagged_value.h"
20 #include "ecmascript/tagged_tree.h"
21
22 namespace panda::ecmascript {
23 using ContainerError = containers::ContainerError;
24 using ErrorFlag = containers::ErrorFlag;
Add(JSThread * thread,const JSHandle<JSAPITreeSet> & set,const JSHandle<JSTaggedValue> & value)25 void JSAPITreeSet::Add(JSThread *thread, const JSHandle<JSAPITreeSet> &set, const JSHandle<JSTaggedValue> &value)
26 {
27 if (!TaggedTreeSet::IsKey(value.GetTaggedValue())) {
28 JSHandle<EcmaString> result = JSTaggedValue::ToString(thread, value.GetTaggedValue());
29 RETURN_IF_ABRUPT_COMPLETION(thread);
30 CString errorMsg =
31 "The type of \"value\" must be Key of JS. Received value is: " + ConvertToString(*result);
32 JSTaggedValue error = ContainerError::BusinessError(thread, ErrorFlag::TYPE_ERROR, errorMsg.c_str());
33 THROW_NEW_ERROR_AND_RETURN(thread, error);
34 }
35 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject()));
36
37 JSTaggedValue newSet = TaggedTreeSet::Add(thread, setHandle, value);
38 RETURN_IF_ABRUPT_COMPLETION(thread);
39 set->SetTreeSet(thread, newSet);
40 }
41
GetSize() const42 int JSAPITreeSet::GetSize() const
43 {
44 return TaggedTreeSet::Cast(GetTreeSet().GetTaggedObject())->NumberOfElements();
45 }
46
GetKey(int entry) const47 JSTaggedValue JSAPITreeSet::GetKey(int entry) const
48 {
49 ASSERT_PRINT(entry < GetSize(), "entry must less than capacity");
50 JSTaggedValue key = TaggedTreeSet::Cast(GetTreeSet().GetTaggedObject())->GetKey(entry);
51 return key.IsHole() ? JSTaggedValue::Undefined() : key;
52 }
53
Delete(JSThread * thread,const JSHandle<JSAPITreeSet> & set,const JSHandle<JSTaggedValue> & key)54 bool JSAPITreeSet::Delete(JSThread *thread, const JSHandle<JSAPITreeSet> &set, const JSHandle<JSTaggedValue> &key)
55 {
56 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject()));
57
58 int entry = TaggedTreeSet::FindEntry(thread, setHandle, key);
59 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
60 if (entry < 0) {
61 return false;
62 }
63 JSTaggedValue newSet = TaggedTreeSet::Delete(thread, setHandle, entry);
64 set->SetTreeSet(thread, newSet);
65 return true;
66 }
67
Has(JSThread * thread,const JSHandle<JSAPITreeSet> & set,const JSHandle<JSTaggedValue> & key)68 bool JSAPITreeSet::Has(JSThread *thread, const JSHandle<JSAPITreeSet> &set, const JSHandle<JSTaggedValue> &key)
69 {
70 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject()));
71 return TaggedTreeSet::FindEntry(thread, setHandle, key) >= 0;
72 }
73
Clear(const JSThread * thread,const JSHandle<JSAPITreeSet> & set)74 void JSAPITreeSet::Clear(const JSThread *thread, const JSHandle<JSAPITreeSet> &set)
75 {
76 int cap = set->GetSize();
77 JSTaggedValue internal = TaggedTreeSet::Create(thread, cap);
78 set->SetTreeSet(thread, internal);
79 }
80
PopFirst(JSThread * thread,const JSHandle<JSAPITreeSet> & set)81 JSTaggedValue JSAPITreeSet::PopFirst(JSThread *thread, const JSHandle<JSAPITreeSet> &set)
82 {
83 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject()));
84 int entry = setHandle->GetMinimum(setHandle->GetRootEntries());
85 if (entry < 0) {
86 return JSTaggedValue::Undefined();
87 }
88 JSHandle<JSTaggedValue> value(thread, setHandle->GetKey(entry));
89 JSTaggedValue newSet = TaggedTreeSet::Delete(thread, setHandle, entry);
90 set->SetTreeSet(thread, newSet);
91 return value.GetTaggedValue();
92 }
93
PopLast(JSThread * thread,const JSHandle<JSAPITreeSet> & set)94 JSTaggedValue JSAPITreeSet::PopLast(JSThread *thread, const JSHandle<JSAPITreeSet> &set)
95 {
96 JSHandle<TaggedTreeSet> setHandle(thread, TaggedTreeSet::Cast(set->GetTreeSet().GetTaggedObject()));
97 int entry = setHandle->GetMaximum(setHandle->GetRootEntries());
98 if (entry < 0) {
99 return JSTaggedValue::Undefined();
100 }
101 JSHandle<JSTaggedValue> value(thread, setHandle->GetKey(entry));
102 JSTaggedValue newSet = TaggedTreeSet::Delete(thread, setHandle, entry);
103 set->SetTreeSet(thread, newSet);
104 return value.GetTaggedValue();
105 }
106 } // namespace panda::ecmascript
107