From ad5896e7666a9ec34da1279bcaaa06241a1cf046 Mon Sep 17 00:00:00 2001 From: wangyong Date: Thu, 6 Jan 2022 10:49:36 +0800 Subject: [PATCH] Add TS linear container class Signed-off-by: wangyong --- container/BUILD.gn | 133 ++++++ container/arraylist/js_arraylist.ts | 296 +++++++++++++ .../arraylist/native_module_arraylist.cpp | 65 +++ container/build_ts_js.py | 55 +++ container/deque/js_deque.ts | 194 +++++++++ container/deque/native_module_deque.cpp | 65 +++ container/linkedlist/js_linkedlist.ts | 401 ++++++++++++++++++ .../linkedlist/native_module_linkedlist.cpp | 67 +++ container/list/js_list.ts | 363 ++++++++++++++++ container/list/native_module_list.cpp | 64 +++ container/queue/js_queue.ts | 149 +++++++ container/queue/native_module_queue.cpp | 65 +++ container/stack/js_stack.ts | 151 +++++++ container/stack/native_module_stack.cpp | 66 +++ container/tsconfig.json | 16 + container/vector/js_vector.ts | 344 +++++++++++++++ container/vector/native_module_vector.cpp | 64 +++ ohos.build | 3 +- 18 files changed, 2560 insertions(+), 1 deletion(-) create mode 100644 container/BUILD.gn create mode 100644 container/arraylist/js_arraylist.ts create mode 100644 container/arraylist/native_module_arraylist.cpp create mode 100755 container/build_ts_js.py create mode 100644 container/deque/js_deque.ts create mode 100644 container/deque/native_module_deque.cpp create mode 100644 container/linkedlist/js_linkedlist.ts create mode 100644 container/linkedlist/native_module_linkedlist.cpp create mode 100644 container/list/js_list.ts create mode 100644 container/list/native_module_list.cpp create mode 100644 container/queue/js_queue.ts create mode 100644 container/queue/native_module_queue.cpp create mode 100644 container/stack/js_stack.ts create mode 100644 container/stack/native_module_stack.cpp create mode 100644 container/tsconfig.json create mode 100644 container/vector/js_vector.ts create mode 100644 container/vector/native_module_vector.cpp diff --git a/container/BUILD.gn b/container/BUILD.gn new file mode 100644 index 0000000..24bf50b --- /dev/null +++ b/container/BUILD.gn @@ -0,0 +1,133 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# 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. + +import("//ark/ts2abc/ts2panda/ts2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") +import("//foundation/ace/ace_engine/ace_config.gni") + +container_names = [ + "arraylist", + "deque", + "queue", + "vector", + "linkedlist", + "list", + "stack", +] + +# compile .ts to .js. +action("build_js_ts") { + script = "//base/compileruntime/js_util_module/container/build_ts_js.py" + args = [ + "--dst-file", + rebase_path(target_out_dir + "/"), + ] + depfile = "$target_gen_dir/$target_name.d" + outputs = [] + foreach(item, container_names) { + dep = target_out_dir + "/js_" + item + ".js" + outputs += [ dep ] + } +} + +# libs +template("container_lib") { + forward_variables_from(invoker, "*") + + name = target_name + base_output_path = get_label_info(":js_" + name, "target_out_dir") + js_container_obj_path = base_output_path + name + ".o" + gen_js_obj("js_" + name) { + input = "$target_out_dir/js_" + name + ".js" + output = js_container_obj_path + dep = ":build_js_ts" + } + + # compile .js to .abc. + action("gen_" + name + "_abc") { + visibility = [ ":*" ] + script = "//ark/ts2abc/ts2panda/scripts/generate_js_bytecode.py" + + args = [ + "--src-js", + rebase_path(target_out_dir + "/js_" + name + ".js"), + "--dst-file", + rebase_path(target_out_dir + "/" + name + ".abc"), + "--node", + rebase_path("${node_path}"), + "--frontend-tool-path", + rebase_path("${ts2abc_build_path}"), + "--node-modules", + rebase_path("${node_modules}"), + "--module", + ] + deps = [ + ":build_js_ts", + "//ark/ts2abc/ts2panda:ark_ts2abc_build", + ] + + inputs = [ target_out_dir + "/js_" + name + ".js" ] + outputs = [ target_out_dir + "/" + name + ".abc" ] + } + + abc_output_path = get_label_info(":" + name + "_abc", "target_out_dir") + arraylist_abc_obj_path = abc_output_path + "/" + name + "_abc.o" + gen_js_obj(name + "_abc") { + input = "$target_out_dir/" + name + ".abc" + output = arraylist_abc_obj_path + dep = ":gen_" + target_name + } + + ohos_shared_library(name) { + include_dirs = [ + "//third_party/node/src", + "//foundation/ace/napi/interfaces/kits", + "//base/compileruntime/js_util_module/container/" + name, + ] + + sources = [ name + "/native_module_" + name + ".cpp" ] + + dep_abc = ":" + name + "_abc" + dep_js = ":js_" + name + deps = [ + "//base/compileruntime/js_util_module/container/:js_" + name, + "//foundation/ace/napi/:ace_napi", + "//utils/native/base:utils", + ] + deps += [ dep_abc ] + deps += [ dep_js ] + + if (is_standard_system) { + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + } else { + external_deps = [ "hilog:libhilog" ] + } + subsystem_name = "ccruntime" + part_name = "jsapi_util" + + relative_install_dir = "module" + } +} + +container_libs = [] +foreach(item, container_names) { + container_lib(item) { + } + dep = ":" + item + container_libs += [ dep ] +} + +group("container_packages") { + deps = container_libs +} diff --git a/container/arraylist/js_arraylist.ts b/container/arraylist/js_arraylist.ts new file mode 100644 index 0000000..7ab4948 --- /dev/null +++ b/container/arraylist/js_arraylist.ts @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +let flag = false; +let fastArrayList = undefined; +let arkPritvate = globalThis["ArkPrivate"] || undefined; +if (arkPritvate !== undefined) { + fastArrayList = arkPritvate.Load(arkPritvate.ArrayList); +} else { + flag = true; +} +if (flag || fastArrayList == undefined) { + class HandlerArrayList { + get(obj: ArrayList, prop: any) { + if (typeof prop === "symbol") { + return obj[prop]; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("ArrayList: get out-of-bounds"); + } + } + return obj[prop]; + } + set(obj: ArrayList, prop: any, value: T) { + if (prop === "_length" || prop === "_capacity") { + obj[prop] = value; + return true; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index > obj.length) { + throw new Error("ArrayList: set out-of-bounds"); + } else { + obj[index] = value; + return true; + } + } + return false; + } + deleteProperty(obj: ArrayList, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("ArrayList: deleteProperty out-of-bounds"); + } + obj.removeByIndex(index); + return true; + } + return false; + } + has(obj: ArrayList, prop: any) { + return obj.has(prop); + } + ownKeys(obj: ArrayList) { + let keys = []; + for (let i = 0; i < obj.length; i++) { + keys.push(i.toString()); + } + return keys; + } + defineProperty(obj: ArrayList, prop: any, desc: any) { + return true; + } + getOwnPropertyDescriptor(obj: ArrayList, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("ArrayList: getOwnPropertyDescriptor out-of-bounds"); + } + return Object.getOwnPropertyDescriptor(obj, prop); + } + return; + } + setPrototypeOf(obj: any, prop: any): T { + throw new Error("Can setPrototype on ArrayList Object"); + } + } + interface IterableIterator { + next: () => { + value: T; + done: boolean; + }; + } + class ArrayList { + private _length: number = 0; + private _capacity: number = 10; + constructor() { + return new Proxy(this, new HandlerArrayList()); + } + get length() { + return this._length; + } + add(element: T): boolean { + if (this.isFull()) { + this.resize(); + } + this[this._length++] = element; + return true; + } + insert(element: T, index: number): void { + if (this.isFull()) { + this.resize(); + } + for (let i = this._length; i > index; i--) { + this[i] = this[i - 1]; + } + this[index] = element; + this._length++; + } + has(element: T): boolean { + for (let i = 0; i < this._length; i++) { + if (this[i] === element) { + return true; + } + } + return false; + } + getIndexOf(element: T): number { + for (let i = 0; i < this._length; i++) { + if (element === this[i]) { + return i; + } + } + return -1; + } + removeByIndex(index: number): void { + for (let i = index; i < this._length - 1; i++) { + this[i] = this[i + 1]; + } + this._length--; + } + remove(element: T): boolean { + if (this.has(element)) { + let index = this.getIndexOf(element); + for (let i = index; i < this._length - 1; i++) { + this[i] = this[i + 1]; + } + this._length--; + return true; + } + return false; + } + getLastIndexOf(element: T): number { + for (let i = this._length - 1; i >= 0; i--) { + if (element === this[i]) { + return i; + } + } + return -1; + } + removeByRange(fromIndex: number, toIndex: number): void { + if (fromIndex >= toIndex) { + throw new Error(`fromIndex cannot be less than or equal to toIndex`); + } + toIndex = toIndex >= this._length - 1 ? this._length - 1 : toIndex; + let i = fromIndex; + for (let j = toIndex; j < this._length; j++) { + this[i] = this[j]; + i++; + } + this._length -= toIndex - fromIndex; + } + replaceAllElements(callbackfn: (value: T, index?: number, arraylist?: ArrayList) => T, + thisArg?: Object): void { + for (let i = 0; i < this._length; i++) { + this[i] = callbackfn.call(thisArg, this[i], i, this); + } + } + forEach(callbackfn: (value: T, index?: number, arraylist?: ArrayList) => void, + thisArg?: Object): void { + for (let i = 0; i < this._length; i++) { + callbackfn.call(thisArg, this[i], i, this); + } + } + sort(comparator?: (firstValue: T, secondValue: T) => number): void { + let isSort = true; + if (comparator) { + for (let i = 0; i < this._length; i++) { + for (let j = 0; j < this._length - 1 - i; j++) { + if (comparator(this[j], this[j + 1]) > 0) { + isSort = false; + let temp = this[j]; + this[j] = this[j + 1]; + this[j + 1] = temp; + } + } + } + } else { + for (var i = 0; i < this.length - 1; i++) { + for (let j = 0; j < this._length - 1 - i; j++) { + if (this.asciSort(this[j], this[j + 1])) { + isSort = false; + let temp = this[j]; + this[j] = this[j + 1]; + this[j + 1] = temp; + } + } + if (isSort) { + break; + } + } + } + } + private asciSort(curElement: any, nextElement: any): boolean { + if ((Object.prototype.toString.call(curElement) === "[object String]" || + Object.prototype.toString.call(curElement) === "[object Number]") && + (Object.prototype.toString.call(nextElement) === "[object String]" || + Object.prototype.toString.call(nextElement) === "[object Number]")) { + curElement = curElement.toString(); + nextElement = nextElement.toString(); + if(curElement > nextElement) { + return true; + } + return false + } + return false; + } + subArrayList(fromIndex: number, toIndex: number): ArrayList { + if (fromIndex >= toIndex) { + throw new Error(`fromIndex cannot be less than or equal to toIndex`); + } + toIndex = toIndex >= this._length - 1 ? this._length - 1 : toIndex; + let arraylist = new ArrayList(); + for (let i = fromIndex; i < toIndex; i++) { + arraylist.add(this[i]); + } + return arraylist; + } + clear(): void { + this._length = 0; + } + clone(): ArrayList { + let clone = new ArrayList(); + for (let i = 0; i < this._length; i++) { + clone.add(this[i]); + } + return clone; + } + getCapacity(): number { + return this._capacity; + } + convertToArray(): Array { + let arr = []; + for (let i = 0; i < this._length; i++) { + arr[i] = this[i]; + } + return arr; + } + private isFull(): boolean { + return this._length === this._capacity; + } + private resize(): void { + this._capacity = 1.5 * this._capacity; + } + increaseCapacityTo(newCapacity: number): void { + if (newCapacity >= this._length) { + this._capacity = newCapacity; + } + } + trimToCurrentSize(): void { + this._capacity = this._length; + } + [Symbol.iterator](): IterableIterator { + let count = 0; + let arraylist = this; + return { + next: function () { + var done = count >= arraylist._length; + var value = !done ? arraylist[count++] : undefined; + return { + done: done, + value: value, + }; + }, + }; + } + } + Object.freeze(ArrayList); + fastArrayList = ArrayList; +} +export default { + ArrayList: fastArrayList, +}; diff --git a/container/arraylist/native_module_arraylist.cpp b/container/arraylist/native_module_arraylist.cpp new file mode 100644 index 0000000..ccfc5d4 --- /dev/null +++ b/container/arraylist/native_module_arraylist.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 "utils/log.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +extern const char _binary_js_arraylist_js_start[]; +extern const char _binary_js_arraylist_js_end[]; +extern const char _binary_arraylist_abc_start[]; +extern const char _binary_arraylist_abc_end[]; + +namespace OHOS::Util { +static napi_value ArrayListInit(napi_env env, napi_value exports) +{ + return exports; +} +extern "C" +__attribute__((visibility("default"))) void NAPI_arraylist_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_js_arraylist_js_start; + } + if (bufLen != nullptr) { + *bufLen = _binary_js_arraylist_js_end - _binary_js_arraylist_js_start; + } +} +extern "C" +__attribute__((visibility("default"))) void NAPI_arraylist_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_arraylist_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_arraylist_abc_end - _binary_arraylist_abc_start; + } +} + +static napi_module arrayListModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = ArrayListInit, + .nm_modname = "ArrayList", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterModule() +{ + napi_module_register(&arrayListModule); +} +} \ No newline at end of file diff --git a/container/build_ts_js.py b/container/build_ts_js.py new file mode 100755 index 0000000..4dbce9e --- /dev/null +++ b/container/build_ts_js.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (c) 2021 Huawei Device Co., Ltd. +# 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. +import os +import platform +import argparse +import subprocess + +def run_command(command): + print(" ".join(command)) + proc = subprocess.Popen(command, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, universal_newlines=True) + out, err = proc.communicate() + if out != "": + print(out) + exit(1) + +if __name__ == '__main__': + + build_path = os.path.abspath(os.path.join(os.getcwd(), "../..")) + os.chdir("%s/base/compileruntime/js_util_module/container/" % build_path) + + parser = argparse.ArgumentParser() + parser.add_argument('--dst-file', + help='the converted target file') + input_arguments = parser.parse_args() + + node = '../../../../prebuilts/build-tools/common/nodejs/\ +node-v12.18.4-linux-x64/bin/node' + tsc = '../../../../ark/ts2abc/ts2panda/node_modules/typescript/bin/tsc' + cmd = [node, tsc] + run_command(cmd) + + for dirname in os.listdir("./jscode") : + filepath = os.path.join("./jscode", dirname) + for filename in os.listdir(filepath) : + dstpath = os.path.join(input_arguments.dst_file, filename) + srcpath = os.path.join(filepath, filename) + cmd = ['cp', "-r", srcpath, dstpath] + run_command(cmd) + + cmd = ['rm', "-rf", './jscode'] + run_command(cmd) + exit(0) diff --git a/container/deque/js_deque.ts b/container/deque/js_deque.ts new file mode 100644 index 0000000..c7f716f --- /dev/null +++ b/container/deque/js_deque.ts @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +let flag = false; +let fastDeque = undefined; +let arkPritvate = globalThis["ArkPrivate"] || undefined; +if (arkPritvate !== undefined) { + fastDeque = arkPritvate.Load(arkPritvate.Deque); +} else { + flag = true; +} +if (flag || fastDeque == undefined) { + class HandlerDeque { + get(obj: Deque, prop: any): T { + if (typeof prop === "symbol") { + return obj[prop]; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0) { + throw new Error("Deque: get out-of-bounds"); + } + } + return obj[prop]; + } + set(obj: Deque, prop: any, value: T): boolean { + if (prop === "_front" || prop === "_capacity" || prop === "_rear") { + obj[prop] = value; + return true; + } + var index = Number(prop); + if (Number.isInteger(index)) { + if (index < 0) { + throw new Error("Deque: set out-of-bounds"); + } else { + obj[index] = value; + return true; + } + } + return false; + } + has(obj: Deque, prop: any) { + return obj.has(prop); + } + ownKeys(obj: Deque) { + let keys = []; + for (let i = 0; i < obj.length; i++) { + keys.push(i.toString()); + } + return keys; + } + defineProperty(obj: Deque, prop: any, desc: any) { + return true; + } + getOwnPropertyDescriptor(obj: Deque, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("Deque: getOwnPropertyDescriptor out-of-bounds"); + } + return Object.getOwnPropertyDescriptor(obj, prop); + } + return; + } + setPrototypeOf(obj: any, prop: any): T { + throw new Error("Can setPrototype on ArrayList Object"); + } + } + interface IterableIterator { + next: () => { + value: T; + done: boolean; + }; + } + class Deque { + private _front: number; + private _capacity: number; + private _rear: number; + constructor() { + this._front = 0; + this._capacity = 8; + this._rear = 0; + return new Proxy(this, new HandlerDeque()); + } + get length(){ + let result = (this._rear - this._front + this._capacity) % this._capacity; + return result; + } + insertFront(element: T): void { + if (this.isFull()) { + this.increaseCapacity(); + } + this._front = (this._front - 1 + this._capacity) % this._capacity; + this[this._front] = element; + } + insertEnd(element: T): void { + if (this.isFull()) { + this.increaseCapacity(); + } + this[this._rear] = element; + this._rear = (this._rear + 1) % (this._capacity + 1); + } + getFirst(): T { + return this[this._front]; + } + getLast(): T { + return this[this._rear - 1]; + } + has(element: T): boolean { + let result = false; + this.forEach(function (value, index) { + if (value == element) { + result = true; + } + }); + return result; + } + popFirst(): T { + let result = this[this._front]; + this._front = (this._front + 1) % (this._capacity + 1); + return result; + } + popLast(): T { + let result = this[this._rear - 1]; + this._rear = (this._rear + this._capacity) % (this._capacity + 1); + return result; + } + forEach(callbackfn: (value: T, index?: number, deque?: Deque) => void, + thisArg?: Object): void { + let k = 0; + let i = this._front; + while (true) { + callbackfn.call(thisArg, this[i], k, this); + i = (i + 1) % this._capacity; + k++; + if (i === this._rear) { + break; + } + } + } + private increaseCapacity(): void { + let count = 0; + let arr = []; + let length = this.length; + while (true) { + arr[count++] = this[this._front]; + this._front = (this._front + 1) % this._capacity; + if (this._front === this._rear) { + break; + } + } + for (let i = 0; i < length; i++) { + this[i] = arr[i]; + } + this._capacity = 2 * this._capacity; + this._front = 0; + this._rear = length; + } + private isFull(): boolean { + return (this._rear + 1) % this._capacity === this._front; + } + [Symbol.iterator](): IterableIterator { + let _this = this; + let count = _this._front; + return { + next: function () { + var done = count == _this._rear; + var value = !done ? _this[count] : undefined; + count = (count + 1) % _this._capacity; + return { + done: done, + value: value, + }; + }, + }; + } + } + Object.freeze(Deque); + fastDeque = Deque; +} +export default { + Deque: fastDeque, +}; diff --git a/container/deque/native_module_deque.cpp b/container/deque/native_module_deque.cpp new file mode 100644 index 0000000..8f2584d --- /dev/null +++ b/container/deque/native_module_deque.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 "utils/log.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +extern const char _binary_js_deque_js_start[]; +extern const char _binary_js_deque_js_end[]; +extern const char _binary_deque_abc_start[]; +extern const char _binary_deque_abc_end[]; +namespace OHOS::Util { +static napi_value DequeInit(napi_env env, napi_value exports) +{ + return exports; +} +extern "C" +__attribute__((visibility("default"))) void NAPI_deque_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_js_deque_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_js_deque_js_end - _binary_js_deque_js_start; + } +} +extern "C" +__attribute__((visibility("default"))) void NAPI_deque_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_deque_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_deque_abc_end - _binary_deque_abc_start; + } +} + +static napi_module dequeModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = DequeInit, + .nm_modname = "Deque", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterModule() +{ + napi_module_register(&dequeModule); +} +} diff --git a/container/linkedlist/js_linkedlist.ts b/container/linkedlist/js_linkedlist.ts new file mode 100644 index 0000000..a5d27e6 --- /dev/null +++ b/container/linkedlist/js_linkedlist.ts @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +let flag = false; +let fastLinkedList = undefined; +let arkPritvate = globalThis["ArkPrivate"] || undefined; +if (arkPritvate !== undefined) { + fastLinkedList = arkPritvate.Load(arkPritvate.LinkedList); +} else { + flag = true; +} +if (flag || fastLinkedList == undefined) { + class HandlerLinkedList { + get(obj: LinkedList, prop: any, receiver: any) { + if (typeof prop === "symbol") { + return obj[prop]; + } + var index = Number.parseInt(prop); + let length = obj.length; + if (Number.isInteger(index)) { + if (index < 0 || index >= length) { + throw new Error("LinkedList: get out-of-bounds"); + } + } + return obj[prop]; + } + set(obj: LinkedList, prop: any, value: any) { + if ( + prop === "_length" || + prop === "_capacity" || + prop === "_head" || + prop == "next" || + prop == "_tail") { + obj[prop] = value; + return true; + } + + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + let length = obj.length; + if (index < 0 || index >= length) { + throw new Error("LinkedList: set out-of-bounds"); + } else { + obj[index] = value; + return true; + } + } + return false; + } + deleteProperty(obj: LinkedList, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + let length = obj.length; + if (index < 0 || index >= length) { + throw new Error("LinkedList: deleteProperty out-of-bounds"); + } + obj.removeByIndex(index); + return true; + } + return false; + } + has(obj: LinkedList, prop: any) { + return obj.has(prop); + } + ownKeys(obj: LinkedList) { + var keys = []; + let length = obj.length; + for (var i = 0; i < length; i++) { + keys.push(i.toString()); + } + return keys; + } + defineProperty(obj: LinkedList, prop: any, desc: any) { + return true; + } + getOwnPropertyDescriptor(obj: LinkedList, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + let length = obj.length; + if (index < 0 || index >= length) { + throw new Error("LinkedList: getOwnPropertyDescriptor out-of-bounds"); + } + return Object.getOwnPropertyDescriptor(obj, prop); + } + return; + } + } + interface IterableIterator { + next: () => { + value: T; + done: boolean; + }; + } + class NodeObj { + /* If 'any' is changed to 'T' here, an error will be reported: + Type 'unknown' cannot be assigned to type 'T'. */ + element: any; + next?: NodeObj | null; + prev?: NodeObj | null; + constructor( + element: any, + next?: NodeObj | null, + prev?: NodeObj | null + ) { + this.element = element; + this.next = next; + this.prev = prev; + } + } + class LinkIterator { + /* If 'any' is changed to 'T' here, an error will be reported: + Property 'next' does not exist on type 'T' */ + private linkNode: any; + constructor(linkNode: any) { + this.linkNode = linkNode; + } + hasNext(): boolean { + if (this.linkNode.next !== null) { + return true; + } else { + return false; + } + } + next(): NodeObj { + this.linkNode = this.linkNode.next; + return this.linkNode; + } + prev(): NodeObj { + this.linkNode = this.linkNode.prev; + return this.linkNode; + } + } + class LinkedList { + private _head?: any; + private _tail?: any; + private _length : number; + private _capacity: number; + constructor(_head?: NodeObj, _tail?: NodeObj) { + this._head = _head || null; + this._tail = _tail || null; + this._length = 0; + this._capacity = 10; + return new Proxy(this, new HandlerLinkedList()); + } + get length() { + return this._length; + } + private getNode(index: number): NodeObj { + let current = this._head; + for (let i = 0; i < index; i++) { + current = current["next"]; + } + return current; + } + get(index: number): T { + let current = this._head; + for (let i = 0; i < index; i++) { + current = current["next"]; + } + return current.element; + } + add(element: T): boolean { + if (this._length === 0) { + let head = this._head; + let tail = this._tail; + this._head = this._tail = new NodeObj(element, head, tail); + } else { + let prevNode = this.getNode(this._length - 1); + prevNode.next = new NodeObj(element, prevNode["next"], this._tail); + } + this._length++; + return true; + } + addFirst(element: T): void { + if (!element) { + throw new Error("element cannot be null"); + } + let node = new NodeObj(element, this._head, this._tail); + if (this._length === 0) { + this._head = this._tail = node; + } else { + node.next = this._head; + this._head = node; + } + this._length++; + } + removeFirst(): T { + let result = this.getNode(0).element; + this.removeByIndex(0); + return result; + } + popFirst(): T { + let result = this.getNode(0).element; + this.removeByIndex(0); + return result; + } + popLast(): T { + let result = this.getNode(this._length - 1).element; + this.removeByIndex(this._length - 1); + return result; + } + removeLast(): T { + let result = this.getNode(this._length - 1).element; + this.removeByIndex(this._length - 1); + return result; + } + clear(): void { + this._head = null; + this._tail = null; + this._length = 0; + } + has(element: T): boolean { + if (this._head.element === element) { + return true; + } + const linkIterator = new LinkIterator(this._head); + while (linkIterator.hasNext()) { + const newNode = linkIterator.next(); + if (newNode.element === element) { + return true; + } + } + return false; + } + getIndexOf(element: T): number { + for (let i = 0; i < this._length; i++) { + const curNode = this.getNode(i); + if (curNode.element === element) { + return i; + } + } + return -1; + } + getLastIndexOf(element: T): number { + for (let i = this._length - 1; i >= 0; i--) { + const curNode = this.getNode(i); + if (curNode.element === element) { + return i; + } + } + return -1; + } + removeByIndex(index: number): T { + let current = this._head; + if (index === 0) { + this._head = current && current.next; + if (this._length == 1) { + this._head = this._tail = null; + } else { + this._head.prev = null; + } + } else if (index == this._length - 1) { + current = this.getNode(index - 1); + this._tail = current; + current.next = null; + } else { + const prevNode = this.getNode(index - 1); + const nextNode = this.getNode(index + 1); + prevNode.next = nextNode; + nextNode.prev = prevNode; + } + this._length--; + return current && current.element; + } + remove(element: T): boolean { + if (this.has(element)) { + let index = this.getIndexOf(element); + this.removeByIndex(index); + return true; + } + return false; + } + removeFirstFound(element: T): boolean { + if (this.has(element)) { + let index = this.getIndexOf(element); + this.removeByIndex(index); + return true; + } else { + return false; + } + } + removeLastFound(element: T): boolean { + if (this.has(element)) { + let index = this.getLastIndexOf(element); + this.removeByIndex(index); + return true; + } else { + return false; + } + } + getFirst(): T { + let newNode = this.getNode(0); + let element = newNode.element; + return element; + } + getLast(): T { + let newNode = this.getNode(this._length - 1); + let element = newNode.element; + return element; + } + insert(index: number, element: T): void { + if (index >= 0 && index < this._length) { + let newNode = new NodeObj(element); + let current = this._head; + if (index === 0) { + if (this._head === null) { + this._head = newNode; + this._tail = newNode; + } else { + newNode.next = this._head; + this._head.prev = newNode; + this._head = newNode; + } + } else { + const prevNode = this.getNode(index - 1); + current = prevNode.next; + newNode.next = current; + prevNode.next = newNode; + current.prev = newNode; + newNode.prev = prevNode; + } + } else if (index === this._length) { + let prevNode = this.getNode(this._length - 1); + prevNode.next = new NodeObj(element, prevNode["next"], this._tail); + } else { + throw new Error("index cannot Less than 0 and more than this length"); + } + this._length++; + } + set(index: number, element: T): T { + const current = this.getNode(index); + current.element = element; + return current && current.element; + } + convertToArray(): Array { + let arr: Array = []; + let index = 0; + if (this._length <= 0) { + return arr; + } + arr[index] = this._head.element; + const linkIterator = new LinkIterator(this._head); + while (linkIterator.hasNext()) { + const newNode = linkIterator.next(); + arr[++index] = newNode.element; + } + return arr; + } + clone(): LinkedList { + let clone = new LinkedList(); + let arr = this.convertToArray(); + for (let i = 0; i < arr.length; i++) { + let item = arr[i] + clone.add(item); + } + return clone; + } + forEach(callbackfn: (value: T,index?: number,linkedlist?: LinkedList) => void, + thisArg?: Object): void { + let index = 0; + const linkIterator = new LinkIterator(this._head); + if (this._length > 0) { + callbackfn.call(thisArg, this._head.element, index, this); + } + while (linkIterator.hasNext()) { + const newNode = linkIterator.next(); + callbackfn.call(thisArg, newNode.element, ++index, this); + } + } + [Symbol.iterator](): IterableIterator { + let count = 0; + let linkedlist = this + return { + next: function () { + var done = count >= linkedlist._length; + var value = !done ? linkedlist.getNode(count++).element : undefined; + return { + done: done, + value: value, + }; + }, + }; + } + } + Object.freeze(LinkedList); + fastLinkedList = LinkedList; +} +export default { + LinkedList: fastLinkedList, +}; diff --git a/container/linkedlist/native_module_linkedlist.cpp b/container/linkedlist/native_module_linkedlist.cpp new file mode 100644 index 0000000..40a8ed0 --- /dev/null +++ b/container/linkedlist/native_module_linkedlist.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 "utils/log.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +extern const char _binary_js_linkedlist_js_start[]; +extern const char _binary_js_linkedlist_js_end[]; +extern const char _binary_linkedlist_abc_start[]; +extern const char _binary_linkedlist_abc_end[]; + +namespace OHOS::Util { +static napi_value LinkedListInit(napi_env env, napi_value exports) +{ + return exports; +} + +extern "C" +__attribute__((visibility("default"))) void NAPI_linkedlist_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_js_linkedlist_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_js_linkedlist_js_end - _binary_js_linkedlist_js_start; + } +} +extern "C" +__attribute__((visibility("default"))) void NAPI_linkedlist_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_linkedlist_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_linkedlist_abc_end - _binary_linkedlist_abc_start; + } +} + +static napi_module linkedListModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = LinkedListInit, + .nm_modname = "LinkedList", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterModule() +{ + napi_module_register(&linkedListModule); +} +} diff --git a/container/list/js_list.ts b/container/list/js_list.ts new file mode 100644 index 0000000..d6f9a24 --- /dev/null +++ b/container/list/js_list.ts @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +let flag = false; +let fastList = undefined; +let arkPritvate = globalThis["ArkPrivate"] || undefined; +if (arkPritvate !== undefined) { + fastList = arkPritvate.Load(arkPritvate.List); +} else { + flag = true; +} +if (flag || fastList == undefined) { + class HandlerList { + get(obj: List, prop: any) { + if (typeof prop === "symbol") { + return obj[prop]; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("List: get out-of-bounds"); + } + } + return obj[prop]; + } + set(obj: List, prop: any, value: T) { + if ( + prop === "_length" || + prop === "_capacity" || + prop === "_head" || + prop == "next") { + obj[prop] = value; + return true; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("List: set out-of-bounds"); + } else { + obj[index] = value; + return true; + } + } + return false; + } + deleteProperty(obj: List, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("List: deleteProperty out-of-bounds"); + } + obj.removeByIndex(index); + return true; + } + return false; + } + has(obj: List, prop: any) { + return obj.has(prop); + } + ownKeys(obj: List) { + var keys = []; + for (var i = 0; i < obj.length; i++) { + keys.push(i.toString()); + } + return keys; + } + defineProperty(obj: List, prop: any, desc: any) { + return true; + } + getOwnPropertyDescriptor(obj: List, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("List: getOwnPropertyDescriptor out-of-bounds"); + } + return Object.getOwnPropertyDescriptor(obj, prop); + } + return; + } + } + interface IterableIterator { + next: () => { + value: T; + done: boolean; + }; + } + class NodeObj { + /* If 'any' is changed to 'T' here, an error will be reported: + Type 'unknown' cannot be assigned to type 'T'. */ + element: any; + next?: NodeObj | null; + constructor(element: any, next?: NodeObj | null) { + this.element = element; + this.next = next; + } + } + class LinkIterator { + /* If 'any' is changed to 'T' here, an error will be reported: + Property 'next' does not exist on type 'T' */ + private linkNode: any; + constructor(linkNode: any) { + this.linkNode = linkNode; + } + hasNext(): boolean { + if (this.linkNode.next !== null) { + return true; + } + return false; + } + next(): NodeObj { + this.linkNode = this.linkNode.next; + return this.linkNode; + } + } + class List { + /* If 'any' is changed to 'NodeObj | null ' here, an error will be reported: + Object may be 'null' */ + private _head: any; + private _length: number; + private _capacity: number; + constructor(_head?: NodeObj) { + this._head = _head || null; + this._length = 0; + this._capacity = 10; + return new Proxy(this, new HandlerList()); + } + get length() { + return this._length; + } + private getNode(index: number): NodeObj { + let current = this._head; + for (let i = 0; i < index; i++) { + current = current["next"]; + } + return current; + } + get(index: number): T { + let current = this._head; + for (let i = 0; i < index; i++) { + current = current["next"]; + } + return current.element; + } + add(element: T): boolean { + if (this._length === 0) { + let head = this._head; + this._head = new NodeObj(element, head); + } else { + let prevNode = this.getNode(this._length - 1); + prevNode.next = new NodeObj(element, prevNode["next"]); + } + this._length++; + return true; + } + clear(): void { + this._head = null; + this._length = 0; + } + has(element: T): boolean { + if (this._head.element === element) { + return true; + } + const linkIterator = new LinkIterator(this._head); + while (linkIterator.hasNext()) { + const newNode = linkIterator.next(); + if (newNode.element === element) { + return true; + } + } + return false; + } + equals(obj: Object): boolean { + if (obj === this) { + return true; + } + if (!(obj instanceof List)) { + return false; + } else { + let e1 = new LinkIterator(this._head); + let e2 = new LinkIterator(obj._head); + while (e1.hasNext() && e2.hasNext()) { + const newNode1 = e1.next(); + const newNode2 = e2.next(); + if (newNode1.element !== newNode2.element) { + return false; + } + } + return !(e1.hasNext() || e2.hasNext()); + } + return true; + } + getIndexOf(element: T): number { + for (let i = 0; i < this._length; i++) { + const curNode = this.getNode(i); + if (curNode.element === element) { + return i; + } + } + return -1; + } + getLastIndexOf(element: T): number { + for (let i = this._length - 1; i >= 0; i--) { + const curNode = this.getNode(i); + if (curNode.element === element) { + return i; + } + } + return -1; + } + removeByIndex(index: number): T { + let oldNode = this._head; + if (index === 0) { + oldNode = this._head; + this._head = oldNode && oldNode.next; + } else { + let prevNode = this.getNode(index - 1); + oldNode = prevNode.next; + prevNode.next = oldNode.next; + } + this._length--; + return oldNode && oldNode.element; + } + remove(element: T): boolean { + if (this.has(element)) { + let index = this.getIndexOf(element); + this.removeByIndex(index); + return true; + } + return false; + } + replaceAllElements(callbackfn: (value: T, index?: number, list?: List) => T, + thisArg?: Object): void { + let index = 0; + const linkIterator = new LinkIterator(this._head); + if (this._length > 0) { + const linkIterator = new LinkIterator(this._head); + this.getNode(index).element = callbackfn.call(thisArg, this._head.element, index, this); + } + while (linkIterator.hasNext()) { + const newNode = linkIterator.next(); + this.getNode(++index).element = callbackfn.call(thisArg, newNode.element, index, this); + } + } + getFirst(): T { + let newNode = this.getNode(0); + let element = newNode.element; + return element; + } + getLast(): T { + let newNode = this.getNode(this._length - 1); + let element = newNode.element; + return element; + } + insert(element: T, index: number): void { + let newNode = new NodeObj(element); + if (index >= 0 && index < this._length) { + if (index === 0) { + const current = this._head; + newNode.next = current; + this._head = newNode; + } else { + const prevNode = this.getNode(index - 1); + newNode.next = prevNode.next; + prevNode.next = newNode; + } + this._length++; + } + } + set(index: number, element: T): T { + const current = this.getNode(index); + current.element = element; + return current && current.element; + } + sort(comparator: (firstValue: T, secondValue: T) => number): void { + let isSort = true; + for (let i = 0; i < this._length; i++) { + for (let j = 0; j < this._length - 1 - i; j++) { + if (comparator(this.getNode(j).element, this.getNode(j + 1).element) > 0) { + isSort = false; + let temp = this.getNode(j).element; + this.getNode(j).element = this.getNode(j + 1).element; + this.getNode(j + 1).element = temp; + } + } + if (isSort) { + break; + } + } + } + getSubList(fromIndex: number, toIndex: number): List { + if (toIndex <= fromIndex) { + throw new Error("toIndex cannot be less than or equal to fromIndex"); + } + toIndex = toIndex > this._length ? this._length - 1 : toIndex; + let list = new List(); + for (let i = fromIndex; i < toIndex; i++) { + let element = this.getNode(i).element; + list.add(element); + if (element === null) { + break; + } + } + return list; + } + convertToArray(): Array { + let arr: Array = []; + let index = 0; + if (this._length <= 0) { + return arr; + } + arr[index] = this._head.element; + const linkIterator = new LinkIterator(this._head); + while (linkIterator.hasNext()) { + const newNode = linkIterator.next(); + arr[++index] = newNode.element; + } + return arr; + } + forEach(callbackfn: (value: T, index?: number, list?: List) => void, + thisArg?: Object): void { + let index = 0; + const linkIterator = new LinkIterator(this._head); + if (this._length > 0) { + const linkIterator = new LinkIterator(this._head); + callbackfn.call(thisArg, this._head.element, index, this); + } + while (linkIterator.hasNext()) { + const newNode = linkIterator.next(); + callbackfn.call(thisArg, newNode.element, ++index, this); + } + } + [Symbol.iterator](): IterableIterator { + let count = 0; + let list = this + return { + next: function () { + var done = count >= list._length; + var value = !done ? list.getNode(count++).element : undefined; + return { + done: done, + value: value, + }; + }, + }; + } + } + Object.freeze(List); + fastList = List; +} +export default { + List: fastList, +}; diff --git a/container/list/native_module_list.cpp b/container/list/native_module_list.cpp new file mode 100644 index 0000000..e8f53b9 --- /dev/null +++ b/container/list/native_module_list.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 "utils/log.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +extern const char _binary_js_list_js_start[]; +extern const char _binary_js_list_js_end[]; +extern const char _binary_list_abc_start[]; +extern const char _binary_list_abc_end[]; +namespace OHOS::Util { +static napi_value ListInit(napi_env env, napi_value exports) +{ + return exports; +} +extern "C" +__attribute__((visibility("default"))) void NAPI_list_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_js_list_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_js_list_js_end - _binary_js_list_js_start; + } +} +extern "C" +__attribute__((visibility("default"))) void NAPI_list_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_list_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_list_abc_end - _binary_list_abc_start; + } +} + +static napi_module listModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = ListInit, + .nm_modname = "List", + .nm_priv = ((void *)0), + .reserved = {0}, +}; +extern "C" __attribute__((constructor)) void RegisterModule() +{ + napi_module_register(&listModule); +} +} diff --git a/container/queue/js_queue.ts b/container/queue/js_queue.ts new file mode 100644 index 0000000..ab2759b --- /dev/null +++ b/container/queue/js_queue.ts @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +let flag = false; +let fastQueue = undefined; +let arkPritvate = globalThis["ArkPrivate"] || undefined; +if (arkPritvate !== undefined) { + fastQueue = arkPritvate.Load(arkPritvate.Queue); +} else { + flag = true; +} +if (flag || fastQueue == undefined) { + class HandlerQueue { + get(obj: Queue, prop: any): T { + if (typeof prop === "symbol") { + return obj[prop]; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index > obj.length) { + throw new Error("Queue: get out-of-bounds"); + } + } + return obj[prop]; + } + set(obj: Queue, prop: any, value: T): boolean { + if (prop === "_front" || prop === "_capacity" || prop === "_rear") { + obj[prop] = value; + return true; + } + var index = Number(prop); + if (Number.isInteger(index)) { + if (index < 0 || index > obj.length) { + throw new Error("Queue: set out-of-bounds"); + } else { + obj[index] = value; + return true; + } + } + return false; + } + ownKeys(obj: Queue) { + var keys = []; + for (var i = 0; i < obj.length; i++) { + keys.push(i.toString()); + } + return keys; + } + defineProperty(obj: Queue, prop: any, desc: any) { + return true; + } + getOwnPropertyDescriptor(obj: Queue, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("Queue: getOwnPropertyDescriptor out-of-bounds"); + } + return Object.getOwnPropertyDescriptor(obj, prop); + } + return; + } + + } + interface IterableIterator { + next: () => { + value: T; + done: boolean; + }; + } + class Queue { + private _front: number; + private _capacity: number; + private _rear: number; + constructor() { + this._front = 0; + this._capacity = 8; + this._rear = 0; + return new Proxy(this, new HandlerQueue()); + } + get length(){ + return this._rear - this._front; + } + add(element: T): boolean { + if (this.isFull()) { + this.increaseCapacity(); + } + this[this._rear] = element; + this._rear = (this._rear + 1) % (this._capacity + 1); + return true; + } + getFirst(): T { + return this[this._front]; + } + pop(): T { + let result = this[this._front]; + this._front = (this._front + 1) % (this._capacity + 1); + return result; + } + forEach(callbackfn: (value: T, index?: number, queue?: Queue) => void, + thisArg?: Object): void { + let k = 0; + let i = this._front; + while (true) { + callbackfn.call(thisArg,this[i], k,this); + i = (i + 1) % this._capacity; + k++; + if (i === this._rear) { + break; + } + } + } + private isFull(): boolean { + return this.length === this._capacity; + } + [Symbol.iterator](): IterableIterator { + let count = this._front; + return { + next: function () { + var done = count == this._rear; + var value = !done ? this[count] : undefined; + count = (count + 1) % this._capacity; + return { + done: done, + value: value, + }; + }, + }; + } + private increaseCapacity(): void { + this._capacity = 2 * this._capacity; + } + } + Object.freeze(Queue); + fastQueue = Queue; +} +export default { + Queue: fastQueue, +}; diff --git a/container/queue/native_module_queue.cpp b/container/queue/native_module_queue.cpp new file mode 100644 index 0000000..758000b --- /dev/null +++ b/container/queue/native_module_queue.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 "utils/log.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +extern const char _binary_js_queue_js_start[]; +extern const char _binary_js_queue_js_end[]; +extern const char _binary_queue_abc_start[]; +extern const char _binary_queue_abc_end[]; +namespace OHOS::Util { +static napi_value QueueInit(napi_env env, napi_value exports) +{ + return exports; +} +extern "C" +__attribute__((visibility("default"))) void NAPI_queue_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_js_queue_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_js_queue_js_end - _binary_js_queue_js_start; + } +} + +extern "C" +__attribute__((visibility("default"))) void NAPI_queue_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_queue_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_queue_abc_end - _binary_queue_abc_start; + } +} + +static napi_module queueModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = QueueInit, + .nm_modname = "Queue", + .nm_priv = ((void *)0), + .reserved = {0}, +}; +extern "C" __attribute__((constructor)) void RegisterModule() +{ + napi_module_register(&queueModule); +} +} diff --git a/container/stack/js_stack.ts b/container/stack/js_stack.ts new file mode 100644 index 0000000..87fa4b0 --- /dev/null +++ b/container/stack/js_stack.ts @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +let flag = false; +let fastStack = undefined; +let arkPritvate = globalThis["ArkPrivate"] || undefined; +if (arkPritvate !== undefined) { + fastStack = arkPritvate.Load(arkPritvate.Stack); +} else { + flag = true; +} +if (flag || fastStack == undefined) { + class HandlerStack { + get(obj: Stack, prop: any) { + if (typeof prop === "symbol") { + return obj[prop]; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + let length = obj.length; + if (index < 0 || index >= length) { + throw new Error("Stack: get out-of-bounds"); + } + } + return obj[prop]; + } + set(obj: Stack, prop: any, value: T) { + if (prop === "_length" || prop === "_capacity") { + obj[prop] = value; + return true; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + let length = obj.length; + if (index < 0 || index >= length) { + throw new Error("Stack: set out-of-bounds"); + } else { + obj[index] = value; + return true; + } + } + return false; + } + ownKeys(obj: Stack) { + var keys = []; + let length = obj.length; + for (var i = 0; i < length; i++) { + keys.push(i.toString()); + } + return keys; + } + defineProperty(obj: Stack, prop: any, desc: any) { + return true; + } + getOwnPropertyDescriptor(obj: Stack, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + let length = obj.length; + if (index < 0 || index >= length) { + throw new Error("Stack: getOwnPropertyDescriptor out-of-bounds"); + } + return Object.getOwnPropertyDescriptor(obj, prop); + } + return; + } + } + interface IterableIterator { + next: () => { + value: T; + done: boolean; + }; + } + class Stack { + private _length: number = 0; + private _capacity: number = 10; + constructor() { + return new Proxy(this, new HandlerStack()); + } + get length() { + return this._length; + } + push(item: T): T { + if (this.isFull()) { + this.increaseCapacity(); + } + this[this._length++] = item; + return item; + } + pop(): T { + let result = this[this.length - 1]; + this._length--; + return result; + } + peek(): T { + return this[this.length - 1]; + } + locate(element: T): number { + for (let i = 0; i < this.length; i++) { + if (this[i] === element) { + return i; + } + } + return -1; + } + isEmpty(): boolean { + return this._length == 0; + } + forEach(callbackfn: (value: T, index?: number, stack?: Stack) => void, + thisArg?: Object): void { + for (let i = 0; i < this.length; i++) { + callbackfn.call(thisArg, this[i], i, this); + } + } + private isFull(): boolean { + return this._length === this._capacity; + } + private increaseCapacity(): void { + this._capacity = 1.5 * this._capacity; + } + [Symbol.iterator](): IterableIterator { + let count = 0; + let stack = this; + return { + next: function () { + var done = count >= stack._length; + var value = !done ? stack[count++] : undefined; + return { + done: done, + value: value, + }; + }, + }; + } + } + Object.freeze(Stack); + fastStack = Stack; +} +export default { + Stack: fastStack, +}; diff --git a/container/stack/native_module_stack.cpp b/container/stack/native_module_stack.cpp new file mode 100644 index 0000000..563d5fb --- /dev/null +++ b/container/stack/native_module_stack.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 "utils/log.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +extern const char _binary_js_stack_js_start[]; +extern const char _binary_js_stack_js_end[]; +extern const char _binary_stack_abc_start[]; +extern const char _binary_stack_abc_end[]; +namespace OHOS::Util { +static napi_value StackInit(napi_env env, napi_value exports) +{ + return exports; +} +extern "C" +__attribute__((visibility("default"))) void NAPI_stack_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_js_stack_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_js_stack_js_end - _binary_js_stack_js_start; + } +} + +extern "C" +__attribute__((visibility("default"))) void NAPI_stack_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_stack_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_stack_abc_end - _binary_stack_abc_start; + } +} + +static napi_module stackModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = StackInit, + .nm_modname = "Stack", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterModule() +{ + napi_module_register(&stackModule); +} +} diff --git a/container/tsconfig.json b/container/tsconfig.json new file mode 100644 index 0000000..cab5e9d --- /dev/null +++ b/container/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "es6", + "rootDir": "./", + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./jscode", /* Specify an output folder for all emitted files. */ + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "noImplicitThis": false, + "suppressImplicitAnyIndexErrors": true + } +} + diff --git a/container/vector/js_vector.ts b/container/vector/js_vector.ts new file mode 100644 index 0000000..a127633 --- /dev/null +++ b/container/vector/js_vector.ts @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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. + */ +let flag = false; +let fastVector = undefined; +let arkPritvate = globalThis["ArkPrivate"] || undefined; +if (arkPritvate !== undefined) { + fastVector = arkPritvate.Load(arkPritvate.Vector); +} else { + flag = true; +} +if (flag || fastVector == undefined) { + class HandlerVector { + get(obj: Vector, prop: any) { + if (typeof prop === "symbol") { + return obj[prop]; + } + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("Vector: get out-of-bounds"); + } + } + return obj[prop]; + } + set(obj: Vector, prop: any, value: T) { + if (prop === "_length" || prop === "_capacity") { + obj[prop] = value; + return true; + } + let index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index > obj.length) { + throw new Error("Vector: set out-of-bounds"); + } else { + obj[index] = value; + return true; + } + } + return false; + } + deleteProperty(obj: Vector, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("vector: deleteProperty out-of-bounds"); + } + obj.removeByIndex(index); + return true; + } + return false; + } + has(obj: Vector, prop: any) { + return obj.has(prop); + } + ownKeys(obj: Vector) { + let keys = []; + for (var i = 0; i < obj.length; i++) { + keys.push(i.toString()); + } + return keys; + } + defineProperty(obj: Vector, prop: any, desc: any) { + return true; + } + getOwnPropertyDescriptor(obj: Vector, prop: any) { + var index = Number.parseInt(prop); + if (Number.isInteger(index)) { + if (index < 0 || index >= obj.length) { + throw new Error("Vector: getOwnPropertyDescriptor out-of-bounds"); + } + return Object.getOwnPropertyDescriptor(obj, prop); + } + return; + } + } + interface IterableIterator { + next: () => { + value: T; + done: boolean; + }; + } + class Vector { + private _length: number = 0; + private _capacity: number = 10; + constructor() { + return new Proxy(this, new HandlerVector()); + } + get length() { + return this._length; + } + add(element: T): boolean { + if (this.isFull()) { + this.resize(); + } + this[this._length++] = element; + return true; + } + insert(element: T, index: number): void { + if (this.isFull()) { + this.resize(); + } + for (let i = this._length; i > index; i--) { + this[i] = this[i - 1]; + } + this[index] = element; + this._length++; + } + has(element: T): boolean { + for (let i = 0; i < this._length; i++) { + if (this[i] === element) { + return true; + } + } + return false; + } + get(index: number): T { + return this[index]; + } + getIndexOf(element: T): number { + for (let i = 0; i < this._length; i++) { + if (element === this[i]) { + return i; + } + } + return -1; + } + getFirstElement(): T { + return this[0]; + } + set(index: number, element: T): void { + this[index] = element; + } + removeByIndex(index: number): void { + for (let i = index; i < this._length - 1; i++) { + this[i] = this[i + 1]; + } + this._length--; + } + remove(element: T): boolean { + if (this.has(element)) { + let index = this.getIndexOf(element); + for (let i = index; i < this._length - 1; i++) { + this[i] = this[i + 1]; + } + this._length--; + return true; + } + return false; + } + getLastElement(): T { + return this[this._length - 1]; + } + getLastIndexOf(element: T): number { + for (let i = this._length - 1; i >= 0; i--) { + if (element === this[i]) { + return i; + } + } + return -1; + } + getLastIndexOfFrom(element: T, index: number): number { + if (this.has(element)) { + for (let i = index; i >= 0; i--) { + if (this[i] === element) { + return i; + } + } + } + return -1; + } + getIndexOfFrom(element: T, index: number): number { + if (this.has(element)) { + for (let i = index; i < this._length; i++) { + if (this[i] === element) { + return i; + } + } + } + return -1; + } + clear(): void { + this._length = 0; + } + removeByRange(fromIndex: number, toIndex: number): void { + if (fromIndex >= toIndex) { + throw new Error(`fromIndex cannot be less than or equal to toIndex`); + } + toIndex = toIndex >= this.length - 1 ? this.length - 1 : toIndex; + let i = fromIndex; + for (let j = toIndex; j < this._length; j++) { + this[i] = this[j]; + i++; + } + this._length -= toIndex - fromIndex; + } + setLength(newSize: number): void { + this._length = newSize; + } + replaceAllElements(callbackfn: (value: T, index?: number, vector?: Vector) => T, + thisArg?: Object): void { + for (let i = 0; i < this._length; i++) { + this[i] = callbackfn.call(thisArg, this[i], i, this); + } + } + forEach(callbackfn: (value: T, index?: number, vector?: Vector) => void, + thisArg?: Object): void { + for (let i = 0; i < this._length; i++) { + callbackfn.call(thisArg, this[i], i, this); + } + } + sort(comparator?: (firstValue: T, secondValue: T) => number): void { + let isSort = true; + if (comparator) { + for (let i = 0; i < this._length; i++) { + for (let j = 0; j < this._length - 1 - i; j++) { + if (comparator(this[j], this[j + 1]) > 0) { + isSort = false; + let temp = this[j]; + this[j] = this[j + 1]; + this[j + 1] = temp; + } + } + } + } else { + for (var i = 0; i < this.length - 1; i++) { + for (let j = 0; j < this._length - 1 - i; j++) { + if (this.asciSort(this[j], this[j + 1])) { + isSort = false; + let temp = this[j]; + this[j] = this[j + 1]; + this[j + 1] = temp; + } + } + if (isSort) { + break; + } + } + } + } + private asciSort(curElement: any, nextElement: any): boolean { + if ((Object.prototype.toString.call(curElement) === "[object String]" || + Object.prototype.toString.call(curElement) === "[object Number]") && + (Object.prototype.toString.call(nextElement) === "[object String]" || + Object.prototype.toString.call(nextElement) === "[object Number]")) { + curElement = curElement.toString(); + nextElement = nextElement.toString(); + if(curElement > nextElement){ + return true + } + return false + } + return false; + } + subVector(fromIndex: number, toIndex: number): Vector { + if (fromIndex >= toIndex) { + throw new Error(`fromIndex cannot be less than or equal to toIndex`); + } + toIndex = toIndex >= this._length - 1 ? this._length - 1 : toIndex; + let vector = new Vector(); + for (let i = fromIndex; i < toIndex; i++) { + vector.add(this[i]); + } + return vector; + } + convertToArray(): Array { + let arr = []; + for (let i = 0; i < this._length; i++) { + arr[i] = this[i]; + } + return arr; + } + copyToArray(array: Array): void { + let arr = this.convertToArray(); + for (let i = 0; i < array.length; i++) { + array[i] = arr[i]; + } + } + toString(): string { + let str = `${this[0]}`; + for (let i = 1; i < this._length; i++) { + str = `${str},${this[i]}`; + } + return str; + } + clone(): Vector { + let clone = new Vector(); + for (let i = 0; i < this._length; i++) { + this.add(this[i]); + } + return clone; + } + getCapacity(): number { + return this._capacity; + } + private isFull(): boolean { + return this._length === this._capacity; + } + private resize(): void { + this._capacity = 2 * this._capacity; + } + increaseCapacityTo(newCapacity: number): void { + if (newCapacity >= this._length) { + this._capacity = newCapacity; + } + } + trimToCurrentSize(): void { + this._capacity = this._length; + } + setSize(newSize: number): void { + this._length = newSize; + } + [Symbol.iterator](): IterableIterator { + let count = 0; + let vector = this + return { + next: function () { + var done = count >= vector._length; + var value = !done ? vector[count++] : undefined; + return { + done: done, + value: value, + }; + }, + }; + } + } + Object.freeze(Vector); + fastVector = Vector; +} +export default { + Vector: fastVector, +}; diff --git a/container/vector/native_module_vector.cpp b/container/vector/native_module_vector.cpp new file mode 100644 index 0000000..c365a1a --- /dev/null +++ b/container/vector/native_module_vector.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 "utils/log.h" +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +extern const char _binary_js_vector_js_start[]; +extern const char _binary_js_vector_js_end[]; +extern const char _binary_vector_abc_start[]; +extern const char _binary_vector_abc_end[]; +namespace OHOS::Util { +static napi_value VectorInit(napi_env env, napi_value exports) +{ + return exports; +} +extern "C" +__attribute__((visibility("default"))) void NAPI_vector_GetJSCode(const char **buf, int *bufLen) +{ + if (buf != nullptr) { + *buf = _binary_js_vector_js_start; + } + + if (bufLen != nullptr) { + *bufLen = _binary_js_vector_js_end - _binary_js_vector_js_start; + } +} + +extern "C" +__attribute__((visibility("default"))) void NAPI_vector_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_vector_abc_start; + } + if (buflen != nullptr) { + *buflen = _binary_vector_abc_end - _binary_vector_abc_start; + } +} +static napi_module vectorModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = VectorInit, + .nm_modname = "Vector", + .nm_priv = ((void *)0), + .reserved = {0}, +}; +extern "C" __attribute__((constructor)) void RegisterModule() +{ + napi_module_register(&vectorModule); +} +} diff --git a/ohos.build b/ohos.build index e5737bd..c14bd95 100755 --- a/ohos.build +++ b/ohos.build @@ -7,7 +7,8 @@ "phone" ], "module_list": [ - "//base/compileruntime/js_util_module/util:util_packages" + "//base/compileruntime/js_util_module/util:util_packages", + "//base/compileruntime/js_util_module/container:container_packages" ], "inner_kits": [ ],