mirror of https://github.com/abpframework/abp
				
				
				
			
							parent
							
								
									2a5fdf7f8b
								
							
						
					
					
						commit
						81600ceb1d
					
				
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								| @ -1,6 +1,5 @@ | ||||
| export * from './common-utils'; | ||||
| export * from './generator-utils'; | ||||
| export * from './initial-utils'; | ||||
| export * from './linked-list'; | ||||
| export * from './route-utils'; | ||||
| export * from './rxjs-utils'; | ||||
|  | ||||
| @ -1,396 +0,0 @@ | ||||
| /* tslint:disable:no-non-null-assertion */ | ||||
| 
 | ||||
| import compare from 'just-compare'; | ||||
| 
 | ||||
| export class ListNode<T = any> { | ||||
|   readonly value: T; | ||||
|   next: ListNode | undefined; | ||||
|   previous: ListNode | undefined; | ||||
| 
 | ||||
|   constructor(value: T) { | ||||
|     this.value = value; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export class LinkedList<T = any> { | ||||
|   private first: ListNode<T> | undefined; | ||||
|   private last: ListNode<T> | undefined; | ||||
|   private size = 0; | ||||
| 
 | ||||
|   get head(): ListNode<T> | undefined { | ||||
|     return this.first; | ||||
|   } | ||||
|   get tail(): ListNode<T> | undefined { | ||||
|     return this.last; | ||||
|   } | ||||
|   get length(): number { | ||||
|     return this.size; | ||||
|   } | ||||
| 
 | ||||
|   private attach( | ||||
|     value: T, | ||||
|     previousNode: ListNode<T> | undefined, | ||||
|     nextNode: ListNode<T> | undefined, | ||||
|   ): ListNode<T> { | ||||
|     if (!previousNode) return this.addHead(value); | ||||
| 
 | ||||
|     if (!nextNode) return this.addTail(value); | ||||
| 
 | ||||
|     const node = new ListNode(value); | ||||
|     node.previous = previousNode; | ||||
|     previousNode.next = node; | ||||
|     node.next = nextNode; | ||||
|     nextNode.previous = node; | ||||
| 
 | ||||
|     this.size++; | ||||
| 
 | ||||
|     return node; | ||||
|   } | ||||
| 
 | ||||
|   private attachMany( | ||||
|     values: T[], | ||||
|     previousNode: ListNode<T> | undefined, | ||||
|     nextNode: ListNode<T> | undefined, | ||||
|   ): ListNode<T>[] { | ||||
|     if (!values.length) return []; | ||||
| 
 | ||||
|     if (!previousNode) return this.addManyHead(values); | ||||
| 
 | ||||
|     if (!nextNode) return this.addManyTail(values); | ||||
| 
 | ||||
|     const list = new LinkedList<T>(); | ||||
|     list.addManyTail(values); | ||||
|     list.first!.previous = previousNode; | ||||
|     previousNode.next = list.first; | ||||
|     list.last!.next = nextNode; | ||||
|     nextNode.previous = list.last; | ||||
| 
 | ||||
|     this.size += values.length; | ||||
| 
 | ||||
|     return list.toNodeArray(); | ||||
|   } | ||||
| 
 | ||||
|   private detach(node: ListNode<T>) { | ||||
|     if (!node.previous) return this.dropHead(); | ||||
| 
 | ||||
|     if (!node.next) return this.dropTail(); | ||||
| 
 | ||||
|     node.previous.next = node.next; | ||||
|     node.next.previous = node.previous; | ||||
| 
 | ||||
|     this.size--; | ||||
| 
 | ||||
|     return node; | ||||
|   } | ||||
| 
 | ||||
|   add(value: T) { | ||||
|     return { | ||||
|       after: (previousValue: T, compareFn: ListComparisonFn<T> = compare) => | ||||
|         this.addAfter(value, previousValue, compareFn), | ||||
|       before: (nextValue: T, compareFn: ListComparisonFn<T> = compare) => | ||||
|         this.addBefore(value, nextValue, compareFn), | ||||
|       byIndex: (position: number) => this.addByIndex(value, position), | ||||
|       head: () => this.addHead(value), | ||||
|       tail: () => this.addTail(value), | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   addMany(values: T[]) { | ||||
|     return { | ||||
|       after: (previousValue: T, compareFn: ListComparisonFn<T> = compare) => | ||||
|         this.addManyAfter(values, previousValue, compareFn), | ||||
|       before: (nextValue: T, compareFn: ListComparisonFn<T> = compare) => | ||||
|         this.addManyBefore(values, nextValue, compareFn), | ||||
|       byIndex: (position: number) => this.addManyByIndex(values, position), | ||||
|       head: () => this.addManyHead(values), | ||||
|       tail: () => this.addManyTail(values), | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   addAfter(value: T, previousValue: T, compareFn: ListComparisonFn<T> = compare): ListNode<T> { | ||||
|     const previous = this.find(node => compareFn(node.value, previousValue)); | ||||
| 
 | ||||
|     return previous ? this.attach(value, previous, previous.next) : this.addTail(value); | ||||
|   } | ||||
| 
 | ||||
|   addBefore(value: T, nextValue: T, compareFn: ListComparisonFn<T> = compare): ListNode<T> { | ||||
|     const next = this.find(node => compareFn(node.value, nextValue)); | ||||
| 
 | ||||
|     return next ? this.attach(value, next.previous, next) : this.addHead(value); | ||||
|   } | ||||
| 
 | ||||
|   addByIndex(value: T, position: number): ListNode<T> { | ||||
|     if (position < 0) position += this.size; | ||||
|     else if (position >= this.size) return this.addTail(value); | ||||
| 
 | ||||
|     if (position <= 0) return this.addHead(value); | ||||
| 
 | ||||
|     const next = this.get(position)!; | ||||
| 
 | ||||
|     return this.attach(value, next.previous, next); | ||||
|   } | ||||
| 
 | ||||
|   addHead(value: T): ListNode<T> { | ||||
|     const node = new ListNode(value); | ||||
| 
 | ||||
|     node.next = this.first; | ||||
| 
 | ||||
|     if (this.first) this.first.previous = node; | ||||
|     else this.last = node; | ||||
| 
 | ||||
|     this.first = node; | ||||
|     this.size++; | ||||
| 
 | ||||
|     return node; | ||||
|   } | ||||
| 
 | ||||
|   addTail(value: T): ListNode<T> { | ||||
|     const node = new ListNode(value); | ||||
| 
 | ||||
|     if (this.first) { | ||||
|       node.previous = this.last; | ||||
|       this.last!.next = node; | ||||
|       this.last = node; | ||||
|     } else { | ||||
|       this.first = node; | ||||
|       this.last = node; | ||||
|     } | ||||
| 
 | ||||
|     this.size++; | ||||
| 
 | ||||
|     return node; | ||||
|   } | ||||
| 
 | ||||
|   addManyAfter( | ||||
|     values: T[], | ||||
|     previousValue: T, | ||||
|     compareFn: ListComparisonFn<T> = compare, | ||||
|   ): ListNode<T>[] { | ||||
|     const previous = this.find(node => compareFn(node.value, previousValue)); | ||||
| 
 | ||||
|     return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values); | ||||
|   } | ||||
| 
 | ||||
|   addManyBefore( | ||||
|     values: T[], | ||||
|     nextValue: T, | ||||
|     compareFn: ListComparisonFn<T> = compare, | ||||
|   ): ListNode<T>[] { | ||||
|     const next = this.find(node => compareFn(node.value, nextValue)); | ||||
| 
 | ||||
|     return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values); | ||||
|   } | ||||
| 
 | ||||
|   addManyByIndex(values: T[], position: number): ListNode<T>[] { | ||||
|     if (position < 0) position += this.size; | ||||
| 
 | ||||
|     if (position <= 0) return this.addManyHead(values); | ||||
| 
 | ||||
|     if (position >= this.size) return this.addManyTail(values); | ||||
| 
 | ||||
|     const next = this.get(position)!; | ||||
| 
 | ||||
|     return this.attachMany(values, next.previous, next); | ||||
|   } | ||||
| 
 | ||||
|   addManyHead(values: T[]): ListNode<T>[] { | ||||
|     return values.reduceRight<ListNode<T>[]>((nodes, value) => { | ||||
|       nodes.unshift(this.addHead(value)); | ||||
|       return nodes; | ||||
|     }, []); | ||||
|   } | ||||
| 
 | ||||
|   addManyTail(values: T[]): ListNode<T>[] { | ||||
|     return values.map(value => this.addTail(value)); | ||||
|   } | ||||
| 
 | ||||
|   drop() { | ||||
|     return { | ||||
|       byIndex: (position: number) => this.dropByIndex(position), | ||||
|       byValue: (value: T, compareFn: ListComparisonFn<T> = compare) => | ||||
|         this.dropByValue(value, compareFn), | ||||
|       byValueAll: (value: T, compareFn: ListComparisonFn<T> = compare) => | ||||
|         this.dropByValueAll(value, compareFn), | ||||
|       head: () => this.dropHead(), | ||||
|       tail: () => this.dropTail(), | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   dropMany(count: number) { | ||||
|     return { | ||||
|       byIndex: (position: number) => this.dropManyByIndex(count, position), | ||||
|       head: () => this.dropManyHead(count), | ||||
|       tail: () => this.dropManyTail(count), | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   dropByIndex(position: number): ListNode<T> | undefined { | ||||
|     if (position < 0) position += this.size; | ||||
| 
 | ||||
|     const current = this.get(position); | ||||
| 
 | ||||
|     return current ? this.detach(current) : undefined; | ||||
|   } | ||||
| 
 | ||||
|   dropByValue(value: T, compareFn: ListComparisonFn<T> = compare): ListNode<T> | undefined { | ||||
|     const position = this.findIndex(node => compareFn(node.value, value)); | ||||
| 
 | ||||
|     return position < 0 ? undefined : this.dropByIndex(position); | ||||
|   } | ||||
| 
 | ||||
|   dropByValueAll(value: T, compareFn: ListComparisonFn<T> = compare): ListNode<T>[] { | ||||
|     const dropped: ListNode<T>[] = []; | ||||
| 
 | ||||
|     for (let current = this.first, position = 0; current; position++, current = current.next) { | ||||
|       if (compareFn(current.value, value)) { | ||||
|         dropped.push(this.dropByIndex(position - dropped.length)!); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     return dropped; | ||||
|   } | ||||
| 
 | ||||
|   dropHead(): ListNode<T> | undefined { | ||||
|     const head = this.first; | ||||
| 
 | ||||
|     if (head) { | ||||
|       this.first = head.next; | ||||
| 
 | ||||
|       if (this.first) this.first.previous = undefined; | ||||
|       else this.last = undefined; | ||||
| 
 | ||||
|       this.size--; | ||||
| 
 | ||||
|       return head; | ||||
|     } | ||||
| 
 | ||||
|     return undefined; | ||||
|   } | ||||
| 
 | ||||
|   dropTail(): ListNode<T> | undefined { | ||||
|     const tail = this.last; | ||||
| 
 | ||||
|     if (tail) { | ||||
|       this.last = tail.previous; | ||||
| 
 | ||||
|       if (this.last) this.last.next = undefined; | ||||
|       else this.first = undefined; | ||||
| 
 | ||||
|       this.size--; | ||||
| 
 | ||||
|       return tail; | ||||
|     } | ||||
| 
 | ||||
|     return undefined; | ||||
|   } | ||||
| 
 | ||||
|   dropManyByIndex(count: number, position: number): ListNode<T>[] { | ||||
|     if (count <= 0) return []; | ||||
| 
 | ||||
|     if (position < 0) position = Math.max(position + this.size, 0); | ||||
|     else if (position >= this.size) return []; | ||||
| 
 | ||||
|     count = Math.min(count, this.size - position); | ||||
| 
 | ||||
|     const dropped: ListNode<T>[] = []; | ||||
| 
 | ||||
|     while (count--) { | ||||
|       const current = this.get(position); | ||||
|       dropped.push(this.detach(current!)!); | ||||
|     } | ||||
| 
 | ||||
|     return dropped; | ||||
|   } | ||||
| 
 | ||||
|   dropManyHead(count: Exclude<number, 0>): ListNode<T>[] { | ||||
|     if (count <= 0) return []; | ||||
| 
 | ||||
|     count = Math.min(count, this.size); | ||||
| 
 | ||||
|     const dropped: ListNode<T>[] = []; | ||||
| 
 | ||||
|     while (count--) dropped.unshift(this.dropHead()!); | ||||
| 
 | ||||
|     return dropped; | ||||
|   } | ||||
| 
 | ||||
|   dropManyTail(count: Exclude<number, 0>): ListNode<T>[] { | ||||
|     if (count <= 0) return []; | ||||
| 
 | ||||
|     count = Math.min(count, this.size); | ||||
| 
 | ||||
|     const dropped: ListNode<T>[] = []; | ||||
| 
 | ||||
|     while (count--) dropped.push(this.dropTail()!); | ||||
| 
 | ||||
|     return dropped; | ||||
|   } | ||||
| 
 | ||||
|   find(predicate: ListIteratorFn<T>): ListNode<T> | undefined { | ||||
|     for (let current = this.first, position = 0; current; position++, current = current.next) { | ||||
|       if (predicate(current, position, this)) return current; | ||||
|     } | ||||
| 
 | ||||
|     return undefined; | ||||
|   } | ||||
| 
 | ||||
|   findIndex(predicate: ListIteratorFn<T>): number { | ||||
|     for (let current = this.first, position = 0; current; position++, current = current.next) { | ||||
|       if (predicate(current, position, this)) return position; | ||||
|     } | ||||
| 
 | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   forEach<R = boolean>(callback: ListIteratorFn<T, R>) { | ||||
|     for (let node = this.first, position = 0; node; position++, node = node.next) { | ||||
|       callback(node, position, this); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   get(position: number): ListNode<T> | undefined { | ||||
|     return this.find((_, index) => position === index); | ||||
|   } | ||||
| 
 | ||||
|   indexOf(value: T, compareFn: ListComparisonFn<T> = compare): number { | ||||
|     return this.findIndex(node => compareFn(node.value, value)); | ||||
|   } | ||||
| 
 | ||||
|   toArray(): T[] { | ||||
|     const array = new Array(this.size); | ||||
| 
 | ||||
|     this.forEach((node, index) => (array[index!] = node.value)); | ||||
| 
 | ||||
|     return array; | ||||
|   } | ||||
| 
 | ||||
|   toNodeArray(): ListNode<T>[] { | ||||
|     const array = new Array(this.size); | ||||
| 
 | ||||
|     this.forEach((node, index) => (array[index!] = node)); | ||||
| 
 | ||||
|     return array; | ||||
|   } | ||||
| 
 | ||||
|   toString(mapperFn: ListMapperFn<T> = JSON.stringify): string { | ||||
|     return this.toArray() | ||||
|       .map(value => mapperFn(value)) | ||||
|       .join(' <-> '); | ||||
|   } | ||||
| 
 | ||||
|   *[Symbol.iterator]() { | ||||
|     for (let node = this.first, position = 0; node; position++, node = node.next) { | ||||
|       yield node.value; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export type ListMapperFn<T = any> = (value: T) => any; | ||||
| 
 | ||||
| export type ListComparisonFn<T = any> = (value1: T, value2: T) => boolean; | ||||
| 
 | ||||
| export type ListIteratorFn<T = any, R = boolean> = ( | ||||
|   node: ListNode<T>, | ||||
|   index?: number, | ||||
|   list?: LinkedList, | ||||
| ) => R; | ||||
					Loading…
					
					
				
		Reference in new issue
	
	 mehmet-erim
						mehmet-erim