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 */ 15interface ArkPrivate { 16 List: number; 17 Load(key: number): Object; 18} 19let flag: boolean = false; 20let fastList: Object = undefined; 21let arkPritvate: ArkPrivate = globalThis['ArkPrivate'] || undefined; 22if (arkPritvate !== undefined) { 23 fastList = arkPritvate.Load(arkPritvate.List); 24} else { 25 flag = true; 26} 27declare function requireNapi(s: string): any; 28if (flag || fastList === undefined) { 29 const {ErrorUtil} = requireNapi('util.struct'); 30 class HandlerList<T> { 31 get(obj: List<T>, prop: any): T { 32 if (typeof prop === 'symbol') { 33 return obj[prop]; 34 } 35 let index: number = Number.parseInt(prop); 36 if (Number.isInteger(index)) { 37 ErrorUtil.checkRangeError("index", index, 0, obj.length - 1); 38 return obj.get(index); 39 } 40 return obj[prop]; 41 } 42 set(obj: List<T>, prop: any, value: T): boolean { 43 if (prop === 'elementNum' || 44 prop === 'capacity' || 45 prop === 'head' || 46 prop === 'next') { 47 obj[prop] = value; 48 return true; 49 } 50 let index: number = Number.parseInt(prop); 51 if (Number.isInteger(index)) { 52 ErrorUtil.checkRangeError("index", index, 0, obj.length); 53 obj.set(index, value); 54 return true; 55 } 56 return false; 57 } 58 deleteProperty(obj: List<T>, prop: any): boolean { 59 let index: number = Number.parseInt(prop); 60 if (Number.isInteger(index)) { 61 ErrorUtil.checkRangeError("index", index, 0, obj.length - 1); 62 obj.removeByIndex(index); 63 return true; 64 } 65 return false; 66 } 67 has(obj: List<T>, prop: any): boolean { 68 return obj.has(prop); 69 } 70 ownKeys(obj: List<T>): Array<string> { 71 let keys: Array<string> = []; 72 for (let i: number = 0; i < obj.length; i++) { 73 keys.push(i.toString()); 74 } 75 return keys; 76 } 77 defineProperty(): boolean { 78 return true; 79 } 80 getOwnPropertyDescriptor(obj: List<T>, prop: any): Object { 81 let index: number = Number.parseInt(prop); 82 if (Number.isInteger(index)) { 83 ErrorUtil.checkRangeError("index", index, 0, obj.length - 1); 84 return Object.getOwnPropertyDescriptor(obj, prop); 85 } 86 return; 87 } 88 setPrototypeOf(): T { 89 throw new Error(`Can't setPrototype on List Object`); 90 } 91 } 92 interface IterableIterator<T> { 93 next: () => { 94 value: T; 95 done: boolean; 96 }; 97 } 98 class NodeObj<T> { 99 element: T; 100 next?: NodeObj<T>; 101 constructor(element: T, next?: NodeObj<T>) { 102 this.element = element; 103 this.next = next; 104 } 105 } 106 class List<T> { 107 private head: NodeObj<T>; 108 private elementNum: number; 109 private capacity: number; 110 constructor() { 111 ErrorUtil.checkNewTargetIsNullError("List", !new.target); 112 this.head = undefined; 113 this.elementNum = 0; 114 this.capacity = 10; 115 return new Proxy(this, new HandlerList()); 116 } 117 get length(): number { 118 return this.elementNum; 119 } 120 private getNode(index: number): NodeObj<T> | undefined { 121 if (index >= 0 && index < this.elementNum) { 122 let current: NodeObj<T> = this.head; 123 for (let i: number = 0; i < index; i++) { 124 if (current !== undefined) { 125 current = current.next; 126 } 127 } 128 return current; 129 } 130 return undefined; 131 } 132 get(index: number): T { 133 ErrorUtil.checkBindError("get", List, this); 134 ErrorUtil.checkTypeError("index", "Integer", index); 135 if (index >= 0 && index < this.elementNum) { 136 let current: NodeObj<T> = this.head; 137 for (let i: number = 0; i < index && current != undefined; i++) { 138 current = current.next; 139 } 140 return current.element; 141 } 142 return undefined; 143 } 144 add(element: T): boolean { 145 ErrorUtil.checkBindError("add", List, this); 146 let node: NodeObj<T> = new NodeObj(element); 147 if (this.head === undefined) { 148 this.head = node; 149 } else { 150 let current: NodeObj<T> = this.head; 151 while (current.next !== undefined) { 152 current = current.next; 153 } 154 current.next = node; 155 } 156 this.elementNum++; 157 return true; 158 } 159 clear(): void { 160 ErrorUtil.checkBindError("clear", List, this); 161 this.head = undefined; 162 this.elementNum = 0; 163 } 164 has(element: T): boolean { 165 ErrorUtil.checkBindError("has", List, this); 166 if (this.head !== undefined) { 167 if (this.head.element === element) { 168 return true; 169 } 170 let current: NodeObj<T> = this.head; 171 while (current.next !== undefined) { 172 current = current.next; 173 if (current.element === element) { 174 return true; 175 } 176 } 177 } 178 return false; 179 } 180 equal(obj: Object): boolean { 181 ErrorUtil.checkBindError("equal", List, this); 182 if (obj === this) { 183 return true; 184 } 185 if (!(obj instanceof List)) { 186 return false; 187 } else { 188 let e1: NodeObj<T> = this.head; 189 let e2: NodeObj<T> = obj.head; 190 if (e1 !== undefined && e2 !== undefined) { 191 while (e1.next !== undefined && e2.next !== undefined) { 192 e1 = e1.next; 193 e2 = e2.next; 194 if (e1.element !== e2.element) { 195 return false; 196 } 197 } 198 return !(e1.next !== undefined || e2.next !== undefined); 199 } else if (e1 !== undefined && e2 === undefined) { 200 return false; 201 } else if (e1 === undefined && e2 !== undefined) { 202 return false; 203 } else { 204 return true; 205 } 206 } 207 } 208 getIndexOf(element: T): number { 209 ErrorUtil.checkBindError("getIndexOf", List, this); 210 for (let i: number = 0; i < this.elementNum; i++) { 211 let curNode: NodeObj<T> = undefined; 212 curNode = this.getNode(i); 213 if (curNode !== undefined && curNode.element === element) { 214 return i; 215 } 216 } 217 return -1; 218 } 219 getLastIndexOf(element: T): number { 220 ErrorUtil.checkBindError("getLastIndexOf", List, this); 221 for (let i: number = this.elementNum - 1; i >= 0; i--) { 222 let curNode: NodeObj<T> = undefined; 223 curNode = this.getNode(i); 224 if (curNode !== undefined && curNode.element === element) { 225 return i; 226 } 227 } 228 return -1; 229 } 230 removeByIndex(index: number): T { 231 ErrorUtil.checkBindError("removeByIndex", List, this); 232 ErrorUtil.checkTypeError("index", "Integer", index); 233 ErrorUtil.checkRangeError("index", index, 0, this.elementNum - 1); 234 let oldNode: NodeObj<T> = this.head; 235 if (index === 0) { 236 oldNode = this.head; 237 this.head = oldNode && oldNode.next; 238 } else { 239 let prevNode: NodeObj<T> = undefined; 240 prevNode = this.getNode(index - 1); 241 oldNode = prevNode.next; 242 prevNode.next = oldNode.next; 243 } 244 this.elementNum--; 245 return oldNode && oldNode.element; 246 } 247 remove(element: T): boolean { 248 ErrorUtil.checkBindError("remove", List, this); 249 if (this.has(element)) { 250 let index: number = 0; 251 index = this.getIndexOf(element); 252 this.removeByIndex(index); 253 return true; 254 } 255 return false; 256 } 257 replaceAllElements(callbackfn: (value: T, index?: number, list?: List<T>) => T, 258 thisArg?: Object): void { 259 ErrorUtil.checkBindError("replaceAllElements", List, this); 260 ErrorUtil.checkTypeError("callbackfn", "callable", callbackfn); 261 let index: number = 0; 262 if (this.head !== undefined) { 263 let current: NodeObj<T> = this.head; 264 if (this.elementNum > 0) { 265 this.getNode(index).element = callbackfn.call(thisArg, this.head.element, index, this); 266 } 267 while (current.next !== undefined) { 268 current = current.next; 269 this.getNode(++index).element = callbackfn.call(thisArg, current.element, index, this); 270 } 271 } 272 } 273 getFirst(): T { 274 ErrorUtil.checkBindError("getFirst", List, this); 275 if (this.isEmpty()) { 276 return undefined; 277 } 278 let element: T = this.head.element; 279 return element; 280 } 281 getLast(): T { 282 ErrorUtil.checkBindError("getLast", List, this); 283 if (this.isEmpty()) { 284 return undefined; 285 } 286 let newNode: NodeObj<T> = undefined; 287 newNode = this.getNode(this.elementNum - 1); 288 let element: T = newNode.element; 289 return element; 290 } 291 insert(element: T, index: number): void { 292 ErrorUtil.checkBindError("insert", List, this); 293 ErrorUtil.checkTypeError("index", "Integer", index); 294 ErrorUtil.checkRangeError("index", index, 0, this.elementNum); 295 let newNode: NodeObj<T> = undefined; 296 newNode = new NodeObj(element); 297 if (index === 0) { 298 let current: NodeObj<T> = this.head; 299 newNode.next = current; 300 this.head = newNode; 301 } else { 302 let prevNode: NodeObj<T> = undefined; 303 prevNode = this.getNode(index - 1); 304 newNode.next = prevNode.next; 305 prevNode.next = newNode; 306 } 307 this.elementNum++; 308 } 309 set(index: number, element: T): T { 310 ErrorUtil.checkBindError("set", List, this); 311 ErrorUtil.checkTypeError("index", "Integer", index); 312 ErrorUtil.checkRangeError("index", index, 0, this.length - 1); 313 let current: NodeObj<T> = undefined; 314 current = this.getNode(index); 315 current.element = element; 316 return current.element; 317 } 318 sort(comparator: (firstValue: T, secondValue: T) => number): void { 319 ErrorUtil.checkBindError("sort", List, this); 320 ErrorUtil.checkTypeError("comparator", "callable", comparator); 321 let isSort: boolean = true; 322 for (let i: number = 0; i < this.elementNum; i++) { 323 for (let j: number = 0; j < this.elementNum - 1 - i; j++) { 324 if ( 325 comparator(this.getNode(j).element, this.getNode(j + 1).element) > 0 326 ) { 327 isSort = false; 328 let temp: T = undefined; 329 temp = this.getNode(j).element; 330 this.getNode(j).element = this.getNode(j + 1).element; 331 this.getNode(j + 1).element = temp; 332 } 333 } 334 if (isSort) { 335 break; 336 } 337 } 338 } 339 getSubList(fromIndex: number, toIndex: number): List<T> { 340 ErrorUtil.checkBindError("getSubList", List, this); 341 ErrorUtil.checkTypeError("fromIndex", "Integer", fromIndex); 342 ErrorUtil.checkTypeError("toIndex", "Integer", toIndex); 343 ErrorUtil.checkRangeError("fromIndex", fromIndex, 0, 344 (toIndex > this.elementNum) ? this.elementNum - 1 : toIndex - 1); 345 ErrorUtil.checkRangeError("toIndex", toIndex, 0, this.elementNum); 346 let list: List<T> = new List<T>(); 347 for (let i: number = fromIndex; i < toIndex; i++) { 348 let element: T = undefined; 349 element = this.getNode(i).element; 350 list.add(element); 351 if (element === undefined) { 352 break; 353 } 354 } 355 return list; 356 } 357 convertToArray(): Array<T> { 358 ErrorUtil.checkBindError("convertToArray", List, this); 359 let arr: Array<T> = []; 360 let index: number = 0; 361 if (this.elementNum <= 0) { 362 return arr; 363 } 364 if (this.head !== undefined) { 365 let current: NodeObj<T> = this.head; 366 arr[index] = this.head.element; 367 while (current.next !== undefined) { 368 current = current.next; 369 arr[++index] = current.element; 370 } 371 } 372 return arr; 373 } 374 isEmpty(): boolean { 375 ErrorUtil.checkBindError("isEmpty", List, this); 376 return this.elementNum === 0; 377 } 378 forEach(callbackfn: (value: T, index?: number, list?: List<T>) => void, 379 thisArg?: Object): void { 380 ErrorUtil.checkBindError("forEach", List, this); 381 ErrorUtil.checkTypeError("callbackfn", "callable", callbackfn); 382 let index: number = 0; 383 if (this.head !== undefined) { 384 let current: NodeObj<T> = this.head; 385 if (this.elementNum > 0) { 386 callbackfn.call(thisArg, this.head.element, index, this); 387 } 388 while (current.next !== undefined) { 389 current = current.next; 390 callbackfn.call(thisArg, current.element, ++index, this); 391 } 392 } 393 } 394 [Symbol.iterator](): IterableIterator<T> { 395 ErrorUtil.checkBindError("Symbol.iterator", List, this); 396 let count: number = 0; 397 let list: List<T> = this; 398 return { 399 next: function () { 400 let done: boolean = false; 401 let value: T = undefined; 402 done = count >= list.elementNum; 403 value = done ? undefined : list.getNode(count++).element; 404 return { 405 done: done, 406 value: value, 407 }; 408 }, 409 }; 410 } 411 } 412 Object.freeze(List); 413 fastList = List; 414} 415export default fastList; 416