Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
e526bbfa
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e526bbfa
编写于
10月 30, 2017
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
tst - compare strings inplace instead of allocating
上级
f502f703
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
184 addition
and
96 deletion
+184
-96
src/vs/base/common/map.ts
src/vs/base/common/map.ts
+138
-91
src/vs/base/test/common/map.test.ts
src/vs/base/test/common/map.test.ts
+46
-5
未找到文件。
src/vs/base/common/map.ts
浏览文件 @
e526bbfa
...
...
@@ -220,78 +220,121 @@ export class BoundedMap<T> {
}
}
export
interface
IKey
Segements
{
export
interface
IKey
Iterator
{
reset
(
key
:
string
):
this
;
join
(
segments
:
string
[]):
string
;
next
():
this
;
join
(
parts
:
string
[]):
string
;
hasNext
():
boolean
;
next
():
string
;
cmp
(
a
:
string
):
number
;
value
():
string
;
}
export
class
StringSegments
implements
IKeySegements
{
private
_value
:
string
;
private
_pos
:
number
;
export
class
StringIterator
implements
IKeyIterator
{
private
_value
:
string
=
''
;
private
_pos
:
number
=
0
;
reset
(
key
:
string
):
this
{
this
.
_value
=
key
;
this
.
_pos
=
0
;
return
this
;
}
join
(
segments
:
string
[]):
string
{
return
segments
.
join
(
''
);
next
():
this
{
this
.
_pos
+=
1
;
return
this
;
}
join
(
parts
:
string
[]):
string
{
return
parts
.
join
(
''
);
}
hasNext
():
boolean
{
return
this
.
_pos
<
this
.
_value
.
length
;
return
this
.
_pos
<
this
.
_value
.
length
-
1
;
}
cmp
(
a
:
string
):
number
{
let
aCode
=
a
.
charCodeAt
(
0
);
let
thisCode
=
this
.
_value
.
charCodeAt
(
this
.
_pos
);
return
aCode
-
thisCode
;
}
next
():
string
{
return
this
.
_value
[
this
.
_pos
++
];
value
():
string
{
return
this
.
_value
[
this
.
_pos
];
}
}
export
class
Path
Segments
implements
IKeySegements
{
export
class
Path
Iterator
implements
IKeyIterator
{
private
static
_fwd
=
'
/
'
.
charCodeAt
(
0
);
private
static
_bwd
=
'
\\
'
.
charCodeAt
(
0
);
private
_value
:
string
;
private
_pos
:
number
;
private
_from
:
number
;
private
_to
:
number
;
reset
(
key
:
string
):
this
{
this
.
_value
=
key
;
this
.
_pos
=
0
;
return
this
;
}
join
(
segments
:
string
[]):
string
{
return
segments
.
join
(
'
/
'
);
this
.
_value
=
key
.
replace
(
/
\\
$|
\/
$/
,
''
);
this
.
_from
=
0
;
this
.
_to
=
0
;
return
this
.
next
();
}
hasNext
():
boolean
{
return
this
.
_pos
<
this
.
_value
.
length
;
return
this
.
_to
<
this
.
_value
.
length
;
}
join
(
parts
:
string
[]):
string
{
return
parts
.
join
(
'
/
'
);
}
next
():
string
{
next
():
this
{
// this._data = key.split(/[\\/]/).filter(s => !!s);
let
pos
=
this
.
_pos
;
loop
:
for
(;
pos
<
this
.
_value
.
length
;
pos
++
)
{
switch
(
this
.
_value
.
charCodeAt
(
pos
))
{
case
PathSegments
.
_fwd
:
case
PathSegments
.
_bwd
:
// found it
break
loop
;
this
.
_from
=
this
.
_to
;
let
justSeps
=
true
;
for
(;
this
.
_to
<
this
.
_value
.
length
;
this
.
_to
++
)
{
const
ch
=
this
.
_value
.
charCodeAt
(
this
.
_to
);
if
(
ch
===
PathIterator
.
_fwd
||
ch
===
PathIterator
.
_bwd
)
{
if
(
justSeps
)
{
this
.
_from
++
;
}
else
{
break
;
}
}
else
{
justSeps
=
false
;
}
}
return
this
;
}
if
(
pos
>
this
.
_pos
)
{
// did advance
let
ret
=
this
.
_value
.
substring
(
this
.
_pos
,
pos
)
;
this
.
_pos
=
pos
+
1
;
return
ret
;
cmp
(
a
:
string
):
number
{
let
aPos
=
0
;
let
aLen
=
a
.
length
;
let
thisPos
=
this
.
_from
;
while
(
aPos
<
aLen
&&
thisPos
<
this
.
_to
)
{
let
cmp
=
a
.
charCodeAt
(
aPos
)
-
this
.
_value
.
charCodeAt
(
thisPos
);
if
(
cmp
!==
0
)
{
return
cmp
;
}
aPos
+=
1
;
thisPos
+=
1
;
}
if
(
aLen
===
this
.
_to
-
this
.
_from
)
{
return
0
;
}
else
if
(
aPos
<
aLen
)
{
return
-
1
;
}
else
{
// maybe just separators in a row
this
.
_pos
+=
1
;
return
this
.
hasNext
()
?
this
.
next
()
:
undefined
;
return
1
;
}
}
value
():
string
{
return
this
.
_value
.
substring
(
this
.
_from
,
this
.
_to
);
}
}
class
TernarySearchTreeNode
<
E
>
{
...
...
@@ -309,18 +352,18 @@ class TernarySearchTreeNode<E> {
export
class
TernarySearchTree
<
E
>
{
static
forPaths
<
E
>
():
TernarySearchTree
<
E
>
{
return
new
TernarySearchTree
<
E
>
(
new
Path
Segments
());
return
new
TernarySearchTree
<
E
>
(
new
Path
Iterator
());
}
static
forStrings
<
E
>
():
TernarySearchTree
<
E
>
{
return
new
TernarySearchTree
<
E
>
(
new
String
Segments
());
return
new
TernarySearchTree
<
E
>
(
new
String
Iterator
());
}
private
_
segments
:
IKeySegements
;
private
_
iter
:
IKeyIterator
;
private
_root
:
TernarySearchTreeNode
<
E
>
;
constructor
(
segments
:
IKey
Segements
)
{
this
.
_
segments
=
segments
;
constructor
(
segments
:
IKey
Iterator
)
{
this
.
_
iter
=
segments
;
}
clear
():
void
{
...
...
@@ -328,26 +371,26 @@ export class TernarySearchTree<E> {
}
set
(
key
:
string
,
element
:
E
):
void
{
const
segements
=
this
.
_segments
.
reset
(
key
);
this
.
_root
=
this
.
_set
(
this
.
_root
,
segements
.
next
(),
segements
,
element
);
this
.
_root
=
this
.
_set
(
this
.
_root
,
this
.
_iter
.
reset
(
key
),
element
);
}
private
_set
(
node
:
TernarySearchTreeNode
<
E
>
,
key
:
string
,
segments
:
IKeySegements
,
element
:
E
):
TernarySearchTreeNode
<
E
>
{
private
_set
(
node
:
TernarySearchTreeNode
<
E
>
,
iter
:
IKeyIterator
,
element
:
E
):
TernarySearchTreeNode
<
E
>
{
if
(
!
node
)
{
node
=
new
TernarySearchTreeNode
<
E
>
();
node
.
str
=
key
;
node
.
str
=
iter
.
value
()
;
}
if
(
node
.
str
>
key
)
{
const
cmp
=
iter
.
cmp
(
node
.
str
);
if
(
cmp
>
0
)
{
// left
node
.
left
=
this
.
_set
(
node
.
left
,
key
,
segments
,
element
);
}
else
if
(
node
.
str
<
key
)
{
node
.
left
=
this
.
_set
(
node
.
left
,
iter
,
element
);
}
else
if
(
cmp
<
0
)
{
// right
node
.
right
=
this
.
_set
(
node
.
right
,
key
,
segments
,
element
);
}
else
if
(
segments
.
hasNext
())
{
node
.
right
=
this
.
_set
(
node
.
right
,
iter
,
element
);
}
else
if
(
iter
.
hasNext
())
{
// mid
node
.
mid
=
this
.
_set
(
node
.
mid
,
segments
.
next
(),
segments
,
element
);
node
.
mid
=
this
.
_set
(
node
.
mid
,
iter
.
next
()
,
element
);
}
else
{
node
.
element
=
element
;
}
...
...
@@ -356,44 +399,46 @@ export class TernarySearchTree<E> {
}
get
(
key
:
string
):
E
{
const
segements
=
this
.
_segments
.
reset
(
key
);
return
this
.
_get
(
this
.
_root
,
segements
.
next
(),
segements
);
return
this
.
_get
(
this
.
_root
,
this
.
_iter
.
reset
(
key
));
}
private
_get
(
node
:
TernarySearchTreeNode
<
E
>
,
key
:
string
,
segments
:
IKeySegements
):
E
{
private
_get
(
node
:
TernarySearchTreeNode
<
E
>
,
iter
:
IKeyIterator
):
E
{
if
(
!
node
)
{
return
undefined
;
}
else
if
(
node
.
str
>
key
)
{
}
const
cmp
=
iter
.
cmp
(
node
.
str
);
if
(
cmp
>
0
)
{
// left
return
this
.
_get
(
node
.
left
,
key
,
segments
);
}
else
if
(
node
.
str
<
key
)
{
return
this
.
_get
(
node
.
left
,
iter
);
}
else
if
(
cmp
<
0
)
{
// right
return
this
.
_get
(
node
.
right
,
key
,
segments
);
}
else
if
(
segments
.
hasNext
())
{
return
this
.
_get
(
node
.
right
,
iter
);
}
else
if
(
iter
.
hasNext
())
{
// mid
return
this
.
_get
(
node
.
mid
,
segments
.
next
(),
segments
);
return
this
.
_get
(
node
.
mid
,
iter
.
next
()
);
}
else
{
return
node
.
element
;
}
}
delete
(
key
:
string
):
void
{
const
segments
=
this
.
_segments
.
reset
(
key
);
this
.
_delete
(
this
.
_root
,
segments
.
next
(),
segments
);
this
.
_delete
(
this
.
_root
,
this
.
_iter
.
reset
(
key
));
}
private
_delete
(
node
:
TernarySearchTreeNode
<
E
>
,
key
:
string
,
segments
:
IKeySegements
):
TernarySearchTreeNode
<
E
>
{
private
_delete
(
node
:
TernarySearchTreeNode
<
E
>
,
iter
:
IKeyIterator
):
TernarySearchTreeNode
<
E
>
{
if
(
!
node
)
{
return
undefined
;
}
else
if
(
node
.
str
>
key
)
{
}
const
cmp
=
iter
.
cmp
(
node
.
str
);
if
(
cmp
>
0
)
{
// left
node
.
left
=
this
.
_delete
(
node
.
left
,
key
,
segments
);
}
else
if
(
node
.
str
<
key
)
{
node
.
left
=
this
.
_delete
(
node
.
left
,
iter
);
}
else
if
(
cmp
<
0
)
{
// right
node
.
right
=
this
.
_delete
(
node
.
right
,
key
,
segments
);
}
else
if
(
segments
.
hasNext
())
{
node
.
right
=
this
.
_delete
(
node
.
right
,
iter
);
}
else
if
(
iter
.
hasNext
())
{
// mid
node
.
mid
=
this
.
_delete
(
node
.
mid
,
segments
.
next
(),
segments
);
node
.
mid
=
this
.
_delete
(
node
.
mid
,
iter
.
next
()
);
}
else
{
// remove element
node
.
element
=
undefined
;
...
...
@@ -403,50 +448,52 @@ export class TernarySearchTree<E> {
}
findSubstr
(
key
:
string
):
E
{
const
segements
=
this
.
_segments
.
reset
(
key
);
return
this
.
_findSubstr
(
this
.
_root
,
segements
.
next
(),
segements
,
undefined
);
return
this
.
_findSubstr
(
this
.
_root
,
this
.
_iter
.
reset
(
key
),
undefined
);
}
private
_findSubstr
(
node
:
TernarySearchTreeNode
<
E
>
,
key
:
string
,
segments
:
IKeySegements
,
candidate
:
E
):
E
{
private
_findSubstr
(
node
:
TernarySearchTreeNode
<
E
>
,
iter
:
IKeyIterator
,
candidate
:
E
):
E
{
if
(
!
node
)
{
return
candidate
;
}
else
if
(
node
.
str
>
key
)
{
}
const
cmp
=
iter
.
cmp
(
node
.
str
);
if
(
cmp
>
0
)
{
// left
return
this
.
_findSubstr
(
node
.
left
,
key
,
segments
,
candidate
);
}
else
if
(
node
.
str
<
key
)
{
return
this
.
_findSubstr
(
node
.
left
,
iter
,
candidate
);
}
else
if
(
cmp
<
0
)
{
// right
return
this
.
_findSubstr
(
node
.
right
,
key
,
segments
,
candidate
);
}
else
if
(
segments
.
hasNext
())
{
return
this
.
_findSubstr
(
node
.
right
,
iter
,
candidate
);
}
else
if
(
iter
.
hasNext
())
{
// mid
return
this
.
_findSubstr
(
node
.
mid
,
segments
.
next
(),
segments
,
node
.
element
||
candidate
);
return
this
.
_findSubstr
(
node
.
mid
,
iter
.
next
()
,
node
.
element
||
candidate
);
}
else
{
return
node
.
element
||
candidate
;
}
}
findSuperstr
(
key
:
string
):
TernarySearchTree
<
E
>
{
const
segements
=
this
.
_segments
.
reset
(
key
);
return
this
.
_findSuperstr
(
this
.
_root
,
segements
.
next
(),
segements
);
return
this
.
_findSuperstr
(
this
.
_root
,
this
.
_iter
.
reset
(
key
));
}
private
_findSuperstr
(
node
:
TernarySearchTreeNode
<
E
>
,
key
:
string
,
segments
:
IKeySegements
):
TernarySearchTree
<
E
>
{
private
_findSuperstr
(
node
:
TernarySearchTreeNode
<
E
>
,
iter
:
IKeyIterator
):
TernarySearchTree
<
E
>
{
if
(
!
node
)
{
return
undefined
;
}
else
if
(
node
.
str
>
key
)
{
}
const
cmp
=
iter
.
cmp
(
node
.
str
);
if
(
cmp
>
0
)
{
// left
return
this
.
_findSuperstr
(
node
.
left
,
key
,
segments
);
}
else
if
(
node
.
str
<
key
)
{
return
this
.
_findSuperstr
(
node
.
left
,
iter
);
}
else
if
(
cmp
<
0
)
{
// right
return
this
.
_findSuperstr
(
node
.
right
,
key
,
segments
);
}
else
if
(
segments
.
hasNext
())
{
return
this
.
_findSuperstr
(
node
.
right
,
iter
);
}
else
if
(
iter
.
hasNext
())
{
// mid
return
this
.
_findSuperstr
(
node
.
mid
,
segments
.
next
(),
segments
);
return
this
.
_findSuperstr
(
node
.
mid
,
iter
.
next
()
);
}
else
{
// collect
if
(
!
node
.
mid
)
{
return
undefined
;
}
let
ret
=
new
TernarySearchTree
<
E
>
(
this
.
_
segments
);
let
ret
=
new
TernarySearchTree
<
E
>
(
this
.
_
iter
);
ret
.
_root
=
node
.
mid
;
return
ret
;
}
...
...
@@ -465,7 +512,7 @@ export class TernarySearchTree<E> {
let
newParts
=
parts
.
slice
();
newParts
.
push
(
node
.
str
);
if
(
node
.
element
)
{
callback
(
node
.
element
,
this
.
_
segments
.
join
(
newParts
));
callback
(
node
.
element
,
this
.
_
iter
.
join
(
newParts
));
}
this
.
_forEach
(
node
.
mid
,
newParts
,
callback
);
}
...
...
src/vs/base/test/common/map.test.ts
浏览文件 @
e526bbfa
...
...
@@ -6,7 +6,7 @@
'
use strict
'
;
import
{
BoundedMap
,
ResourceMap
,
TernarySearchTree
,
StringSegments
,
PathSegments
}
from
'
vs/base/common/map
'
;
import
{
BoundedMap
,
ResourceMap
,
TernarySearchTree
,
PathIterator
,
StringIterator
}
from
'
vs/base/common/map
'
;
import
*
as
assert
from
'
assert
'
;
import
URI
from
'
vs/base/common/uri
'
;
...
...
@@ -311,6 +311,47 @@ suite('Map', () => {
assert
.
ok
(
!
map
.
has
(
'
4
'
));
});
test
(
'
PathIterator
'
,
function
()
{
const
iter
=
new
PathIterator
();
iter
.
reset
(
'
file:///usr/bin/file.txt
'
);
assert
.
equal
(
iter
.
value
(),
'
file:
'
);
assert
.
equal
(
iter
.
hasNext
(),
true
);
assert
.
equal
(
iter
.
cmp
(
'
file:
'
),
0
);
assert
.
ok
(
iter
.
cmp
(
'
a
'
)
<
0
);
assert
.
ok
(
iter
.
cmp
(
'
aile:
'
)
<
0
);
assert
.
ok
(
iter
.
cmp
(
'
z
'
)
>
0
);
assert
.
ok
(
iter
.
cmp
(
'
zile:
'
)
>
0
);
iter
.
next
();
assert
.
equal
(
iter
.
value
(),
'
usr
'
);
assert
.
equal
(
iter
.
hasNext
(),
true
);
iter
.
next
();
assert
.
equal
(
iter
.
value
(),
'
bin
'
);
assert
.
equal
(
iter
.
hasNext
(),
true
);
iter
.
next
();
assert
.
equal
(
iter
.
value
(),
'
file.txt
'
);
assert
.
equal
(
iter
.
hasNext
(),
false
);
iter
.
next
();
assert
.
equal
(
iter
.
value
(),
''
);
assert
.
equal
(
iter
.
hasNext
(),
false
);
iter
.
next
();
assert
.
equal
(
iter
.
value
(),
''
);
assert
.
equal
(
iter
.
hasNext
(),
false
);
//
iter
.
reset
(
'
/foo/bar/
'
);
assert
.
equal
(
iter
.
value
(),
'
foo
'
);
assert
.
equal
(
iter
.
hasNext
(),
true
);
iter
.
next
();
assert
.
equal
(
iter
.
value
(),
'
bar
'
);
assert
.
equal
(
iter
.
hasNext
(),
false
);
});
function
assertTernarySearchTree
<
E
>
(
trie
:
TernarySearchTree
<
E
>
,
...
elements
:
[
string
,
E
][])
{
const
map
=
new
Map
<
string
,
E
>
();
for
(
const
[
key
,
value
]
of
elements
)
{
...
...
@@ -377,7 +418,7 @@ suite('Map', () => {
});
test
(
'
TernarySearchTree - basics
'
,
function
()
{
let
trie
=
new
TernarySearchTree
<
number
>
(
new
String
Segments
());
let
trie
=
new
TernarySearchTree
<
number
>
(
new
String
Iterator
());
trie
.
set
(
'
foo
'
,
1
);
trie
.
set
(
'
bar
'
,
2
);
...
...
@@ -407,7 +448,7 @@ suite('Map', () => {
});
test
(
'
TernarySearchTree (PathSegments) - basics
'
,
function
()
{
let
trie
=
new
TernarySearchTree
<
number
>
(
new
Path
Segments
());
let
trie
=
new
TernarySearchTree
<
number
>
(
new
Path
Iterator
());
trie
.
set
(
'
/user/foo/bar
'
,
1
);
trie
.
set
(
'
/user/foo
'
,
2
);
...
...
@@ -431,7 +472,7 @@ suite('Map', () => {
test
(
'
TernarySearchTree (PathSegments) - lookup
'
,
function
()
{
const
map
=
new
TernarySearchTree
<
number
>
(
new
Path
Segments
());
const
map
=
new
TernarySearchTree
<
number
>
(
new
Path
Iterator
());
map
.
set
(
'
/user/foo/bar
'
,
1
);
map
.
set
(
'
/user/foo
'
,
2
);
map
.
set
(
'
/user/foo/flip/flop
'
,
3
);
...
...
@@ -445,7 +486,7 @@ suite('Map', () => {
test
(
'
TernarySearchTree (PathSegments) - superstr
'
,
function
()
{
const
map
=
new
TernarySearchTree
<
number
>
(
new
Path
Segments
());
const
map
=
new
TernarySearchTree
<
number
>
(
new
Path
Iterator
());
map
.
set
(
'
/user/foo/bar
'
,
1
);
map
.
set
(
'
/user/foo
'
,
2
);
map
.
set
(
'
/user/foo/flip/flop
'
,
3
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录