Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
a91a8042
Commit
a91a8042
authored
Apr 11, 2009
by
Ken Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
range over strings
R=r OCL=27332 CL=27332
parent
72d86766
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
235 additions
and
2 deletions
+235
-2
builtin.c.boot
src/cmd/gc/builtin.c.boot
+2
-0
sys.go
src/cmd/gc/sys.go
+2
-0
walk.c
src/cmd/gc/walk.c
+75
-2
string.c
src/runtime/string.c
+156
-0
No files found.
src/cmd/gc/builtin.c.boot
View file @
a91a8042
...
...
@@ -20,6 +20,8 @@ char *sysimport =
"func sys.intstring (? int64) (? string)\n"
"func sys.byteastring (? *uint8, ? int) (? string)\n"
"func sys.arraystring (? []uint8) (? string)\n"
"func sys.stringiter (? string, ? int) (? int)\n"
"func sys.stringiter2 (? string, ? int) (retk int, retv int)\n"
"func sys.ifaceT2I (sigi *uint8, sigt *uint8, elem any) (ret any)\n"
"func sys.ifaceI2T (sigt *uint8, iface any) (ret any)\n"
"func sys.ifaceI2T2 (sigt *uint8, iface any) (ret any, ok bool)\n"
...
...
src/cmd/gc/sys.go
View file @
a91a8042
...
...
@@ -29,6 +29,8 @@ func indexstring(string, int) byte;
func
intstring
(
int64
)
string
;
func
byteastring
(
*
byte
,
int
)
string
;
func
arraystring
([]
byte
)
string
;
func
stringiter
(
string
,
int
)
int
;
func
stringiter2
(
string
,
int
)
(
retk
int
,
retv
int
);
func
ifaceT2I
(
sigi
*
byte
,
sigt
*
byte
,
elem
any
)
(
ret
any
);
func
ifaceI2T
(
sigt
*
byte
,
iface
any
)
(
ret
any
);
...
...
src/cmd/gc/walk.c
View file @
a91a8042
...
...
@@ -3191,7 +3191,7 @@ badt:
* rewrite a range statement
* k and v are names/new_names
* m is an array or map
* local is
=/0 or :=/1
* local is
0 (meaning =) or 1 (meaning :=)
*/
Node
*
dorange
(
Node
*
nn
)
...
...
@@ -3227,8 +3227,10 @@ dorange(Node *nn)
goto
map
;
if
(
t
->
etype
==
TCHAN
)
goto
chan
;
if
(
t
->
etype
==
TSTRING
)
goto
strng
;
yyerror
(
"range must be over map/array"
);
yyerror
(
"range must be over map/array
/chan/string
"
);
goto
out
;
ary:
...
...
@@ -3333,6 +3335,77 @@ chan:
addtotop
(
n
);
goto
out
;
strng:
hk
=
nod
(
OXXX
,
N
,
N
);
// hidden key
tempname
(
hk
,
types
[
TINT
]);
ha
=
nod
(
OXXX
,
N
,
N
);
// hidden string
tempname
(
ha
,
t
);
if
(
local
)
{
k
=
old2new
(
k
,
types
[
TINT
]);
if
(
v
!=
N
)
v
=
old2new
(
v
,
types
[
TINT
]);
}
// ha = s
a
=
nod
(
OAS
,
ha
,
m
);
n
->
ninit
=
a
;
// kh = 0
a
=
nod
(
OAS
,
hk
,
nodintconst
(
0
));
n
->
ninit
=
list
(
n
->
ninit
,
a
);
// k = hk
a
=
nod
(
OAS
,
k
,
hk
);
n
->
ninit
=
list
(
n
->
ninit
,
a
);
// hk[,v] = stringiter(ha,hk)
if
(
v
!=
N
)
{
// hk,v = stringiter2(ha, hk)
on
=
syslook
(
"stringiter2"
,
0
);
// argtype(on, v->type);
a
=
list
(
ha
,
hk
);
a
=
nod
(
OCALL
,
on
,
a
);
a
=
nod
(
OAS
,
list
(
hk
,
v
),
a
);
}
else
{
// hk = stringiter(ha, hk)
on
=
syslook
(
"stringiter"
,
0
);
a
=
list
(
ha
,
hk
);
a
=
nod
(
OCALL
,
on
,
a
);
a
=
nod
(
OAS
,
hk
,
a
);
}
n
->
ninit
=
list
(
n
->
ninit
,
a
);
// while(hk != 0)
n
->
ntest
=
nod
(
ONE
,
hk
,
nodintconst
(
0
));
// k = hk
a
=
nod
(
OAS
,
k
,
hk
);
n
->
nincr
=
a
;
// hk[,v] = stringiter(ha,hk)
if
(
v
!=
N
)
{
// hk,v = stringiter2(ha, hk)
on
=
syslook
(
"stringiter2"
,
0
);
// argtype(on, v->type);
a
=
list
(
ha
,
hk
);
a
=
nod
(
OCALL
,
on
,
a
);
a
=
nod
(
OAS
,
list
(
hk
,
v
),
a
);
}
else
{
// hk = stringiter(ha, hk)
on
=
syslook
(
"stringiter"
,
0
);
a
=
list
(
ha
,
hk
);
a
=
nod
(
OCALL
,
on
,
a
);
a
=
nod
(
OAS
,
hk
,
a
);
}
n
->
nincr
=
list
(
n
->
nincr
,
a
);
addtotop
(
n
);
goto
out
;
out:
return
n
;
}
...
...
src/runtime/string.c
View file @
a91a8042
...
...
@@ -188,3 +188,159 @@ sys·arraystring(Array b, String s)
mcpy
(
s
.
str
,
b
.
array
,
s
.
len
);
FLUSH
(
&
s
);
}
static
int32
chartorune
(
int32
*
rune
,
byte
*
str
);
enum
{
Runeself
=
0x80
,
Runeerror
=
0xfff8
,
// fffd in plan9
};
// func stringiter(string, int) (retk int);
void
sys
·
stringiter
(
String
s
,
int32
k
,
int32
retk
)
{
int32
l
,
n
;
if
(
k
>=
s
.
len
)
{
// retk=0 is end of iteration
retk
=
0
;
goto
out
;
}
l
=
s
.
str
[
k
];
n
=
1
;
if
(
l
>=
Runeself
)
{
// multi-char rune
n
=
chartorune
(
&
l
,
s
.
str
+
k
);
if
(
k
+
n
>
s
.
len
)
{
// special case of multi-char rune
// that ran off end of string
l
=
Runeerror
;
n
=
1
;
}
}
retk
=
k
+
n
;
out
:
FLUSH
(
&
retk
);
}
// func stringiter2(string, int) (retk int, retv any);
void
sys
·
stringiter2
(
String
s
,
int32
k
,
int32
retk
,
int32
retv
)
{
int32
l
,
n
;
if
(
k
>=
s
.
len
)
{
// retk=0 is end of iteration
retk
=
0
;
retv
=
0
;
goto
out
;
}
l
=
s
.
str
[
k
];
n
=
1
;
if
(
l
>=
Runeself
)
{
// multi-char rune
n
=
chartorune
(
&
l
,
s
.
str
+
k
);
if
(
k
+
n
>
s
.
len
)
{
// special case of multi-char rune
// that ran off end of string
l
=
Runeerror
;
n
=
1
;
}
}
retk
=
k
+
n
;
retv
=
l
;
out
:
FLUSH
(
&
retk
);
FLUSH
(
&
retv
);
}
//
// copied from plan9 library
//
enum
{
Bit1
=
7
,
Bitx
=
6
,
Bit2
=
5
,
Bit3
=
4
,
Bit4
=
3
,
T1
=
((
1
<<
(
Bit1
+
1
))
-
1
)
^
0xFF
,
/* 0000 0000 */
Tx
=
((
1
<<
(
Bitx
+
1
))
-
1
)
^
0xFF
,
/* 1000 0000 */
T2
=
((
1
<<
(
Bit2
+
1
))
-
1
)
^
0xFF
,
/* 1100 0000 */
T3
=
((
1
<<
(
Bit3
+
1
))
-
1
)
^
0xFF
,
/* 1110 0000 */
T4
=
((
1
<<
(
Bit4
+
1
))
-
1
)
^
0xFF
,
/* 1111 0000 */
Rune1
=
(
1
<<
(
Bit1
+
0
*
Bitx
))
-
1
,
/* 0000 0000 0111 1111 */
Rune2
=
(
1
<<
(
Bit2
+
1
*
Bitx
))
-
1
,
/* 0000 0111 1111 1111 */
Rune3
=
(
1
<<
(
Bit3
+
2
*
Bitx
))
-
1
,
/* 1111 1111 1111 1111 */
Maskx
=
(
1
<<
Bitx
)
-
1
,
/* 0011 1111 */
Testx
=
Maskx
^
0xFF
,
/* 1100 0000 */
};
static
int32
chartorune
(
int32
*
rune
,
byte
*
str
)
{
int32
c
,
c1
,
c2
;
int32
l
;
/*
* one character sequence
* 00000-0007F => T1
*/
c
=
str
[
0
];
if
(
c
<
Tx
)
{
*
rune
=
c
;
return
1
;
}
/*
* two character sequence
* 0080-07FF => T2 Tx
*/
c1
=
str
[
1
]
^
Tx
;
if
(
c1
&
Testx
)
goto
bad
;
if
(
c
<
T3
)
{
if
(
c
<
T2
)
goto
bad
;
l
=
((
c
<<
Bitx
)
|
c1
)
&
Rune2
;
if
(
l
<=
Rune1
)
goto
bad
;
*
rune
=
l
;
return
2
;
}
/*
* three character sequence
* 0800-FFFF => T3 Tx Tx
*/
c2
=
str
[
2
]
^
Tx
;
if
(
c2
&
Testx
)
goto
bad
;
if
(
c
<
T4
)
{
l
=
((((
c
<<
Bitx
)
|
c1
)
<<
Bitx
)
|
c2
)
&
Rune3
;
if
(
l
<=
Rune2
)
goto
bad
;
*
rune
=
l
;
return
3
;
}
/*
* bad decoding
*/
bad:
*
rune
=
Runeerror
;
return
1
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment